Vítejte na blog.vyvojar.cz Přihlásit | Registrovat | Pomoc

Proč nenávidím var

ale přesto ho používám.

 

Klíčové slovo var je mezi námi v C# již dlouho dobu. Jeho používání se postupně ustálilo, ale v začátcích se objevovalo prakticky ve všech deklaracích proměnných. Třeba jako

var i = 5;

V tomto případě lze ještě při znalosti chování kompilátoru odvodit, že proměnná bude typu Int32. Ale co třeba tohle

var x = i;

Tak tady už bez znalosti kódu nejde určit typ proměnné x. Kód se stává hůř čitelným. V případě složitějších případů to bez nápovědy IDE, bez složitého dohledávání, ani nejde číst. Mám na mysli, například to, že se chci podívat do kódu jen pomocí prostého textového editoru nebo na webu, aniž bych si musel otevírat projekt. Když vidím takhle použité var, snažím se při review ho přepisovat na konkrétní typ.

Přesto se použití var občas nedá rozumně vyhnout. Jasné je to u anonymních typů, ale občas je dobré nechat složitou práci s odvozením typu na kompilátoru. Vezmu kousek kódu

var students = dbContext.Students;
var smiths = students.Where(o => o.LastName == "Smith");

První pokus o přepsání var na konkrétní typy by mohl vypadat třeba takto

IEnumerable<Student> students = dbContext.Students;
IEnumerable<Student> smiths = students.Where(o => o.LastName == "Smith");

A máme v programu zaděláno na průšvih. Podmínku Where totiž nebude vyhodnocovat databázový server, ale nejprve se načtou všichni studenti na klienta a teprve klient bude podmínku vyhodnocovat. A v případě, že bude následovat

int count = smiths.Count();

Tak jsme v rámci čitelnosti kódu donutili server skutečně načíst a a na klienta poslat všechny řádky tabulky studentů, přenést to všechno přes síť, klienta jsme donutili tyto řádky zpracovat a načíst do paměti, převést na instance třídy Student, následně projít všechny instance třídy Student, provést porovnání a vrátit omezenou množinu instancí třídy Student a na této omezené množině spočítat kolik jich vlastně je. Místo toho aby se databázový server jednoduše podíval do indexu a poslal nám po síti jedno číslo.

Skutečné typ, které v uvedeném případě vygeneruje kompilátor budou

DbSet<Student> students = dbContext.Students;
IQueryable<Student> smiths = students.Where(o => o.LastName == "Smith");

Ještě by šlo akceptovat přepsání na

IQueryable<Student> students = dbContext.Students;
IQueryable<Student> smiths = students.Where(o => o.LastName == "Smith");

Ale v tomhle případě se opět v rámci čitelnosti, nebo možná jednoduchosti psaní kódu, přikloním k použití var a nechám práci s odvozením typu na kompilátoru.

Posted by arci | 1 Comments
Vedeno pod: ,

Co je to tranzistor

Povídání pro nejmenší.

Z tuhle historku děkuji svému vedoucímu kroužku mladých. Není úplně přesně, ale já si ještě po 30 letech pamatuji ten obrázek, co nám tenkrát k tomu kreslil na tabuli. Nepražáci prominou.

Prahou protéká jedna velká řeka. Její jméno je nezajímavé, ale pokud to chcete vědět, jmenuje se Vltava. Přitéká odněkud z jihu od Českých Budějovic a pokračuje dál až do Labe z kterého se za hranicemi stává Elbe. Do této řeky se vlévá malý potok, který se jmenuje Botič. Na tom Botiči žil blízko soutoku se řekou Vltavou u železničního mostu jeden vodník. Tenhle vodník neměl co práci a a tak si jednoho dne řekl co kdyby zkusil na Vltavě postavy přehradu kterou budu řídit kolik vody bude Vltavou protékat. A jak si řekl tak udělal. Postavil nad soutokem přehradu za začal řídit kolik vody může Vltavou dál protékat. Pořád otáčel kolem, kterým vytahoval a zase spouštěl stavidlo. Po čase ho to přestalo bavit a navíc byl líný a rozhodl se, že si práci zautomatizuje. Napadlo ho, že bude řídit otevření stavidla na řece podle výšky hladiny Botiče. Sestrojil plovák, který podle výšky hladiny Botiče otevíral a nebo zavíral stavidlo. Čím vyšší byla hladina Botiče, tím víc bylo stavidlo otevřené, když v Botiči nebyla žádná voda, stavidlo se úplně zavřelo a do Elbe neteklo vůbec nic. Vodník tak stojí, kouká na to, a povídá “Budu tomu říkat TRANZISTOR”.

Tranzistor

Tranzistor je součástka, která řídí malým proudem přitékajícím do báze, velký proud protékající mezi colectorem a emitorem. To platí pro takzvané bipolární tranzistory, unipolární tranzistory jsou řízeny napětím.

Tranzistor se používá jako zesilovač nebo spínač. Při použití jako zesilovač se pomocí okolních součástek nastavuje tzv. pracovní bod, to znamená, že se konkrétní tranzistor nechá pracovat v jeho nejoptimálnějším rozsahu proudu nebo napětí.

Poznámka na závěr: ve schematické značce NPN (en-pé-en) jde šipka ven.

Posted by arci | 2 Comments
Vedeno pod:

Příprava build serveru pro TFS Online

Proč to dělat

Když nevyhovuje hosted build server. To znamená v případě, že potřebujete v procesu buildu používat knihovny, které nejsou dostupné jako NuGet balíček (ten používat jde, ale chce to opravit změny nuget.targets). Nebo nějaká vlastní konfigurace prostředí, což je v mém případě instalace certifikátu doménové certifikační autority, protože všechny interní servery mají certifikát vystavený touto certifikační autoritou a to i v případech, kdy jsou dostupné z internetu. Tahle část konfigurace umožní HTTPS komunikaci s interními firemními servery jako důvěryhodnými.

 

Postup instalace

Instalace je jednoduchá, podotýkám, že máme MSDN předplatné a tak používám to co mi nabízí. Proto v prvním kroku využiji Azure Virtual Machine, pro úplně vlastní build server bude prvním krokem nainstalovat operační systém, případně najít vhodný stroj.

Krok 1

Nahodit nový virtuální stroj A1 v Azure Virtual Machines z předpřipravených. Já jsem použil Windows Server 2012 R2, bude to stát cca $57 měsíčně podle ceníku zde. Je nutný stroj minimálně A1, protože instalace vyžaduje minimálně 1GB RAM.

Krok 2

Stáhnout a nainstalovat Visual Studio Team Foundation Server 2013 with Update 4 (x86 and x64) - Web Installer (English) z MSDN, žádný klíč nebude potřeba. Potom podle návodu nainstalovat a nakonfigurovat build server. Ale je to vcelku jednoduché, projít instalací a nakonfigurovat pouze build server controller pro požadovaný účet .visualstudio.com">https://<něco>.visualstudio.com.

Krok 3

Vlastně už nic povinného, build server běží a je schopen práce, ale další instalace umožní použití toho, kvůli čemu jsem to celé dělal – vlastních knihoven a konfigurace prostředí. Takže ty nedůležité kroky, kvůli kterým jsem to celé dělal.

  1. Nainstalovat certifikát doménové certifikační autority
  2. Pro vývoj .Net 4.0 nainstalovat Microsoft Windows SDK for Windows 7 and .NET Framework 4 (tenhle kousek není nutný, pokud nepotřebujete udržovat starší verze vašich produktů a nechcete podporovat Windows Server 2003)
  3. Nainstalovat Windows Software Development Kit (SDK) for Windows 8
  4. Nainstalovat WiX Toolset (v mém případě verze 3.8)
  5. Nainstalovat knihovny třetí strany (v mém případě DevExpress)
Posted by arci | 0 Comments

K čemu je prefer 32-bit

Narazil jsem na otázku: Kdy se aplikace .Net přeložená jako AnyCPU s volbou prefer 32-bit spustí jako 64 bitová? Odpověď je překvapivě jednoduchá. V okamžiku kdy si jí do své aplikační domény natáhne aplikace spuštěná jako 64 bitová.

Máme 2 aplikace Guest a Loader. Guest aplikace je přeložena jako AnyCPU (se zaškrtnutým prefer 32-bit), x86 a x64 a obsahuje jednoduchý kód:

static void Main(string[] args)
{
    Console.WriteLine("Guest application is {0}", IntPtr.Size == 8 ? "x64" : IntPtr.Size == 4 ? "x32" : "Unknown");
}

Když spustíme její verzi AnyCPU z příkazové řádky dostaneme na 64 bitovém systému:

image

Aplikace Loader je složitější:

static void Main(string[] args)
{
    Console.WriteLine("\nLoader application is {0}", IntPtr.Size == 8 ? "x64" : IntPtr.Size == 4 ? "x32" : "Unknown");
    Execute(@"..\..\..\Guest\bin\Debug\Guest.exe");
    Execute(@"..\..\..\Guest\bin\x86\Debug\Guest.exe");
    Execute(@"..\..\..\Guest\bin\x64\Debug\Guest.exe");
    Console.ReadKey(false);
}
static void Execute(string path)
{
    try
    {
        Console.WriteLine("\nExecute: {0}", path);
        AppDomain.CurrentDomain.ExecuteAssembly(path);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Exception: {0}", ex.GetType());
    }
}
Spustíme nejprve Loader ve verzi AnyCPU (bez prefer 32-bit)
image 
Potom spustíme 32 bitovou verzi:
image

Guest přeložený s AnyCPU se přizpůsobuje hostitelské doméně. Pokud si může vybrat spustí se jako 32 bitová aplikace.

A k čemu to je?

Napadá mě scénář, kdy guest aplikace nabízí nějaké funkce a k části z nich potřebuje nějaké nativní knihovny, které existují pouze ve verzi x86 nebo COM. Potom při hostování v 64 bitové aplikaci nabídne místo chyby pouze část svých funkcí, nebo za cenu ztráty výkonu použije nějaký RPC wrapper na 32 bitovou verzi.

Poznámka

Volba prefer 32-bit je dostupná až od verze 4.5 .NET Frameworku

Posted by arci | 0 Comments
Vedeno pod: ,

Vytvoření a publikace NuGet balíčku při buildu

Jednoduché řešení automatizace vytváření NuGet balíčků při buildu aplikace s použitím msbuild a nuget.exe bez dalších komponent. Znalci základů úpoužívání a vytváření NuGet balíčků mohou přeskočit až na krok 3. Předpokládám dále základní znalosti msbuild syntaxe.

Používáme to kvůli automatickým buildům, ale funguje to i z Visual Studia, nemělo by to být závislé na použitém build serveru

Krok 1: Příprava solution

Pro solution nastavíme “Enable NuGet Package Restore”, třeba podle originálního návodu. To přidá k solution adresář .nuget, kde se nachází nuget.exe, který budeme používat dál. Nadále budu předpokládat, že projekt má vlastní podadresář v rámci solution. Pokud tomu tak není, je potřeba upravit cestu k nuget.exe.

Krok 2: Příprava projektu

V adresáři s projektovým souborem spustíme příkaz “..\.nuget\nuget spec”. Tento příkaz vytvoří nuspec soubor, tento soubor vložíme do projektu s nastavením Build Action: None, případně soubor doplníme a upravíme. Ponecháme makro $version$, které zajistí vytvoření verze podle AssemblyVersion výsledné knihovny.

Krok 3: Úprava build procesu

Nejprve si otevřeme projektový soubor pro editaci (tady je návod jak) a doplníme AfterBuild target který vytvoří a vypublikuje balíček na server s pomocí příkazové řádky.

<Target Name="AfterBuild" Condition="'$(IsDesktopBuild)'=='false'">

  <PropertyGroup>
    <!-- NuGet BUG? - trailing slash in BasePath causes exception, so remove it -->
    <NugetBasePath Condition="!HasTrailingSlash($(TargetDir))">$(TargetDir)</NugetBasePath>
    <NugetBasePath Condition="HasTrailingSlash($(TargetDir))">$(TargetDir).</NugetBasePath>
    <!-- nuget exe path (relative to project directory) -->
    <NugetExe Condition="'$(NugetExe)'==''">$(MSBuildProjectDirectory)\..\.nuget\nuget.exe</NugetExe>
  </PropertyGroup>

  <!-- Copy files for nuget (nuget hack, because nuget needs \bin\Release folder with dll) -->
  <MakeDir Directories="$(MSBuildProjectDirectory)\$(OutputPath)" Condition="!Exists('$(MSBuildProjectDirectory)\$(OutputPath)')" />
  <Copy SourceFiles="@(IntermediateAssembly)" DestinationFolder="$(MSBuildProjectDirectory)\$(OutputPath)" SkipUnchangedFiles="true" />

  <!-- Delete existing packages -->
  <Delete Files="$(TargetDir)$(ProjectName).*.nupkg" />
  <Exec Command="&quot;$(NugetExe)&quot; pack &quot;$(MSBuildProjectFullPath)&quot; -BasePath &quot;$(NugetBasePath)&quot;"
        WorkingDirectory="$(TargetDir)" ContinueOnError="true" IgnoreExitCode="true" />
  <!-- Create item NugetPackageFile -->
  <CreateItem Include="$(TargetDir)$(ProjectName).*.nupkg">
    <Output ItemName="NugetPackageFile" TaskParameter="Include" />
  </CreateItem>

  <!-- push nuget package to server -->
  <Exec Command="&quot;$(NugetExe)&quot; push &quot;@(NugetPackageFile)&quot; -s http://repo.myserver.cz/nuget/ 00000000-0000-0000-0000-000000000000"
        Condition=" @(NugetPackageFile) != '' " />
</Target>

Celé se to spouští pouze při buildu na serveru (minule jsem psal jak detekovat TFS build server). Při vyřazení podmínky to bude balíček vytvářet a publikovat při každém buildu i z Visual Studia.

Poznámka na závěr

Pro automatické vytvoření NuGet balíčku při buildu aplikace existuje pro Team Foundation Server 2012 doplněk NuGetter který zajistí při použití build serveru vytvoření balíčku i jeho publikaci na NuGet server s komfortním nastavením. Ale mě nevyhovuje třeba proto, že stále ještě používáme TFS2010.

Posted by arci | 0 Comments
Vedeno pod: , ,

Detekce build serveru na TFS 2010

Po upgrade serveru z TFS 2005 na TFS 2010 mi u nově zakládaných projektů chyběla property $(IsDesktopBuild), pomocí které detekoval build server a v případě buildu na vývojářském stroji přeskakoval dlouhotrvající a zbytečné akce. Od VS2005 je k dispozici property $(BuildingInsideVisualStudio), která je nastavena při spuštění z prostředí Visual Studio. Pokud je ale opravdu potřeba detekovat spuštění na build serveru/agentovi, používám následujících pár řádek v csproj souboru:

 

   1: <PropertyGroup Condition=" '$(IsDesktopBuild)'=='' ">
   2:   <IsDesktopBuild>true</IsDesktopBuild>
   3:   <IsDesktopBuild Condition="'$(BuildUri)'!='' and '$(TeamFoundationServerUrl)'!=''">false</IsDesktopBuild>
   4: </PropertyGroup>

Property $(IsDesktopBuild) je nastavena na false pouze na build serveru/agentovi. Podobně jako tomu bylo u starších verzí build serverů.

Není z mé hlavy, našel jsem je na Internetu, ale vážně si nepamatuji kde. Pokud někdo víte původní zdroj, tak ho rád uvedu.

Edit 6.1.2015: Funguje to i na Visual Studio Online Hosted Build Controller

Posted by arci | 0 Comments

Jak na výběr informačního systému

K napsání tohoto povídání mě přivedl příspěvek z 31.3.2009 pod článkem Čárové kódy na webu: Základy, zní: "Chtela bych zavest v logistickem centru prijem a vydej zbozi pres carove kody. Muzete mi poradit, jak postupovat." Protože jsem se v minulosti s podobnou otázkou setkal, pokusím se odpovědět.

Jednoduchá odpověď je: Vy se do toho nepouštějte. Může se totiž stát, že si pořídíte krásný a drahý systém, který bude dělat přesně to co má, ale nebude to to co potřebujete aby dělal. Představte si, že si jdete koupit auto. Prodejce vám nabídne krásné, červené a rychlé auto. Doplní to mnoha fotografiemi a reklamními letáky. Zaplatíte zálohu a za 3 měsíce vám ho dovezou. Je krásné, rychlé a červené. Je to Ferrari, splňuje vše co prodejce říkal, ALE vy máte tři děti a potřebujete auto na to, aby jste je vozila do školy. To ale v krásném sporťáku nepůjde. Chyba se stala hned na začátku, nedomluvili jste se s prodejce na co auto vlastně potřebujete a prodejce zrovna chtěl prodat nějaké to Ferrari. U auta se vám to asi nestane, ale co u informačního systému?

Pozn.: Ano, je to informační systém, nebo jeho část.

Jak vybrat dobře?

Nejlepší by bylo, kdyby zákazník měl špičkové znalosti v oboru informačních systémů, přehled v jejich slabinách a možnostech. Takový ale není. Jsou v zásadě tři možnosti:

  1. Najdu a zaměstnám takového člověka
  2. Najdu konzultantskou firmu, která má takového člověka a té výběr svěřím
  3. Najdu firmu, která to udělá celé

1. Najdu a zaměstnám takového člověka

Najít přímo člověka by bylo fajn, chvíli se ve firmě bude rozkoukávat, pozná její potřeby a potom je bude schopen sdělit dál a ohlídat, že systém bude potřebám firmy vyhovovat. Jenže co s ním po dokončení projektu.

2. Najdu konzultantskou firmu, která má takového člověka a té výběr svěřím

K těmhle firmám mám averzi danou zkušeností. Pokud firma zároveň není realizítorem, budou jí pravděpodobně chybět některé zkušenosti. Není schopna předvést, že dotáhne věci do konce. Její práci nelze zhodnotit, pokud nepočítám dojem.

Jednu takovou jsem potkal dokonce 2x. Na první zakázce byla během výběrového řízení zákazníkem odstraněna. Nedoděla ani výběr, přesto má tuto zakázku ve svých referencích, dokonce napsanou tak, že to vypadá, že systém realizovala.

Ale byl by to ideální stav, bohužel jsem přesvědčen, že výběr takovéto firmy je mnohem těžší a snáze se naletí na reklamní letáky a slogany. Ale pro případný výběr platí stejné věci jako pro třetí možnost.

3. Výběr firmy udělám sám

Ale jak, když nic nevím. Nejlépe je začít tím, že se pokusím formalizovat co nejpřesněji své požadavky. S těmi potom oslovím zájemce o realizaci zakázky.

Oslovené firmy buď podají rovnou nabídku nebo budou chtít znát doplňující informace. Pokud podají rovnou nabídku, znamená to, že jsem sepsal zadání naprosto přesně nebo je nabídka jen podivný odhad. Z otázek firem se můžeme poučit a udělat si obrázek jak bude firma postupovat při další práci. Jestli se bude ptát na náš názor a naše potřeby nebo nám bude vnucovat svoje.

Po obdržení všech nabídek bych vyřadil ty, kteří se neptali, příliš levné i příliš drahé. Mohlo se stát, že jsem během této fáze zjistil, že potřebuji něco trochu jiného. Potom můžu vybrané firmy požádat o přepracování nabídky a zapracování změn.

Může být výhodné si vymínit, že vybraná firma nejdříve udělá důkladnou analýzu a potom případně nabídku upraví. Při této analýze totiž můžeme přijít na další věci. A mám stále možnost zjistit, že mě dodavatel tlačí někam, kde nechci být. A nebude to stát celé peníze na projekt.

První zadání

Nejprve je potřeba pokusit se najít všechny osoby, které s předpokládaným projektem přijdou do styku. Předložit jim předpoklad a zjistit jejich případné požadavky.

Pokud jsme součástí mezinárodní korporace, tak je dobré vědět která omezení nebo výhody mi z toho plynou. Může se jednat třeba o ceny některých komponent, požadavky a podobně.

Abych nebyl obecný, tak tady jsou body které je potřeba připravit, když ne na první zadání, tak určitě před začátkem projektu:

  • Zajistit aby všechno co prochází logistickým centrem mělo čárový kód ve tvaru jaký je potřeba. Tzn. třeba nejen EAN13, ale všechny informace, inspirace třeba na www.gs1cz.org/system-gs1/logisticke-informace-ai. Nepodcenit, může to trvat dlouho.
  • Na které další systémy bude nový systém navázaný. Může se jednat např. o systém odměňování skladníků za odbavené kamiony, docházkový systém, ERP (objednávky, příjemky/výdejky).
  • Jaké výstupy bude systém mít. Třeba výše zmíněný způsob hodnocení skladníků, nebo výstup o čekací době kamionu na naložení/vyložení (potom musí být kousek systému i na vrátnici).
  • Forma prezentace dat (intranet, integrace do stávajícího systému manažerských sestav)
  • Rozdělení budoucích uživatelů do skupin - rolí (skladník, směnový vedoucí, ...)
  • Kolik lidí bude systém používat a jak. Tohle bude mít vliv na počet koncových zařízení nebo licence.
  • Jak dlouho je třeba archivovat data ze systému a jaká. Např. pokud se informace dodávají do ERP, není potřeba informace skladovat příliš dlouho (rok stačí).
  • Jazyk systému (multijazyčnost).
  • Seznam preferovaného/požadovaného hardware a software. Pokud již máme nějaké čtečky ve firmě, bude výhodné mít stejné. Software by mělo být naopak schopno spravovat i naše IT oddělení.
  • Jaké další předpisy platí pro naše prostředí.

Co čekat

  • Projekt bude trvat nějakou dobu a bude vyžadovat naši spolupráci.
  • Projekt bude něco stát, zpravidla je dobré čekat navýšení ceny proti nabídce tak 10 - 15 %
  • Nebude to jednoduché
Posted by arci | 6 Comments
Vedeno pod:

Počítače v průmyslové praxi podruhé

Ve svém minulém povídání jsem uvedl pár postřehů k využití počítačů v průmyslovém prostředí. Rád bych doplnil radu:

Pokud nevíte o co jde, nepouštějte se do toho!.

Příliš mnoho projektů končí neúspěchem jen proto, že se programátor setká s reálným světem. V téhle úvaze se pokusím nastínit některá úskalí. Lidé z průmyslového prostředí jsou obecně méně tolerantní k výpadkům počítače než v kanceláři. Prostě si ještě nezvykli.

Mechanické provedení

Při návrhu aplikace a hlavně použitého hardware je nutné vzít v úvahu prostředí a zvyky lidí. To co projde v kanceláři, je v takovémto prostředí nemožné. Lidé ve výrobě netolerují pády a restarty. A pozor, necháte-li někde neobsazenou zásuvku, je jen otázka času kdy se v ní objeví vrtačka.

Představy IT firem o takovémto prostředí jsou často velmi zkreslené. Nedávno jsme se nechali zlákat a od dodavatele serverů jsme objednali i rack, s tím nás produktový manažer ubezpečoval, že se jedná o provedení do lehkého průmyslu. Přišel rám, bez bočnic a dveře byly z děrovaného plechu. Asi provedení lehký průmysl s klimatizovanou serverovnou.

V reakci na minulé povídání je pár fotek jak lze využít panelové PC a schovat jej do bedny, jinak je lépe se poohlédnout po výrobcích elektrických rozvaděčů, z nichž někteří nabízejí docela pěkné. V každém případě se podívat na krytí IP dle ČSN EN 60529.

Přikládám odkaz na něco veselého na téma krytí IP. Mimochodem v článku uváděná zkratka nn, znamená nízké napětí, což je 50V až 1000V. A to za jistých okolností může zabít. Více třeba zde.

Software

V operačním systému je potřeba nastavit, aby se vše provádělo automaticky a bez zásahu uživatele a nejlépe i bez jakékoliv interakce. To se týká automatických aktualizací (ty je lépe vypnout a dělat ručně), antivirů a podobně. Hodně pomůže pokud je možno oddělit síť pro zařízení ve výrobě od kancelářské, nejlépe tak, že server má 2 síťové karty. Takhle se podařilo přežít i opravdu masivní útok červa, kdy z kancelářských počítačů se odstraňoval několik dní. Ono totiž občas jsou tyto sítě korporátní a to znamená několik časových pásem a spoustu počítačů.

Speciální harware a periferie

Tím myslím všechno co se k počítači ve výrobě připojuje a nemáte to zrovna na stole. Jedná se o čtečky čárového kódu a identifikačních čipů, speciální tiskárny, různé displeje (jako jsou pokladní), váhy, menší či větší stroje nebo celé výrobní linky a technologie. Čím je inteligentnější tím tužší odpor klade vůči jakémukoliv ovlivňování své funkce ze strany jakéhokoliv jiného programu.

Lidé

Nebudou rozumět vám a vy nebude rozumět jim. Každý výrobní závod má naprosto jinou terminologii a to někdy i v rámci jedné korporace. Chvíli trvá než se to naučíte. Namátkou, víte co je:

  • ajpina
  • šuskanál
  • roubík
  • tambor
  • džambo / jumbo

Odradil jsem vás? Vlastně jsem to chtěl. Pokud ne a chcete něco dalšího, napište si co.

Posted by arci | 0 Comments
Vedeno pod:

Počítače v průmyslové praxi

K napsání těchto řádek mě inspiroval jeden z komentářů na článek http://www.aspnet.cz/Articles/210-ovladani-led-panelu-sigma-asc-105.aspx. Je to jen pár postřehů k využití počítačů v průmyslové praxi.

Postřeh první (možná ne nejdůležitější)

Vezmete-li obyčejné PC a umístíte-li jej ve výrobě, odejde během prvního týdne. Většinou přes vrátnici. Takové PC ve výrobě je nutno přivázat na pořádné vodítko nebo řetěz, nejlepší je umístit jej do klece, to jeho choutky na odcházení VELMI sníží. V kleci PC vydrží cca 2 roky. Průběžně je potřeba kontrolovat funkci větráků (stačí 2 x ročně). Potom je nutné počítat s tím, že nevydrží pevný disk, případně základní deska. Přeci jen to není konstruované na provoz 24 hodin denně. CRT monitor má vypálené znaky tak po 2 až 3 měsících, ale nejméně rok se s tím dá žít. Existují varianty počítačů bez točivých částí, ale ne vždy je možné je použít.

Postřech druhý (ergonomie)

Ergonomie ovládání je věc subjektivní. Kromě toho, že je potřeba počítat s lidmi nosícími brýle na blízko i na dálku, vyskytnou se i další anomálie. Potkal jsem se s člověkem barvoslepým, pro kterého bylo nutné vymyslet barevné schéma tak, abychom se vyhnuli barvě kterou nevidí. Umístění monitoru, případně klávesnice je také potřeba pečlivě rozvrhnout.  Kromě toho, že kolem strojů se nevyskytuje mnoho vhodných stolů a vše se musí "věšet", tak musíme myslet na různou výšku operátorů. Bývá to od 160 cm do 2 m, ale opět jsou vyjímky.

Postřeh třetí (počítačová gramotnost)

I když se bude zdát, že pomocný dělník není schopen zvládnou ani jednoduše navrženou obrazovku, tak na nahrání porna nebo hry do počítače je schopný dost. Bohužel některé programy právě pro výrobní sektor potřebují poměrně vysoká práva v operačním systému.

Postřeh čtvrtý (luddismus)

Průmyslová revoluce není mrtvá. Nejnižší forma odporu proti závádění strojů, jejich rozbíjením, je stále účinná. Prostě ten monitor praskl sám, tady kladivo nikdo nemá.

Postřeh pátý (cena)

Ne vždy je nejlevnější věc ta najlepší. Například nejlevnější čtečka čárového kódu stojí cca. 1000 Kč. V dělnické ruce vydrží tak týden. A to přesto, že se nejedná o zlý úmysl. Jeden dodavatel na předváděčce ukazoval zatloukání hřebíků s novým modelem. Za půl roku jsem mu vrátil ten úžasný model umlácený (chybělo sklíčko, tlačítko někdo promáčkl a kryt měl škrábanců požehnaně, v jednom místě byl obroušený skoro o 1 mm). Zjednodušeně řečeno je vždy potřeba volit mezi cenou a "výdrží" a počítat s výměnou.

Postřeh šestý (stáří)

Životnost mechanických částí je výrazně vyšší než elektrických a elektronických. Na internetu se dají najít prodeje strojů i přes 50 let starých a to ne do muzea, ale do výroby. Poslední počítač s Windows 3.11 jsem nahrazoval kolem roku 2005 a to jen kvůli možnosti, že by mohl vysadit a nebyl by náhradní (asi 2 měsíce jsme sháněli síťovou kartu 3C509, kterých svého času byly hromady).

Závěr (Murphyho zákony)

Stejně to není všechno a na něco jste zapomněli! Vynalézavost lidí nezná hranic. A náhoda je ...

Posted by arci | 3 Comments
Vedeno pod:

Team Build a automatické verzování

Simple description of one way how to setup automatic versioning and Team Build (Team Foundation Server 2005), including WiX

Krátký popis jak se dá nastavit automatické verzování na Team Build Serveru (Team Foundation Server 2002), včetně změny verze pro WiX.

Popis je rozdělen do několika částí popisující jednotlivé kroky. Není je však potřeba provádět přesně v popsaném pořadí, některé lze i vynechat. V popisu je zdůvodněno proč se co dělá, ale není to úplný návod.

Všechny projekty v solution mají vložen odkaz na soubor pojmenovaný SolutionVersion.cs, který je součástí solution a je při automatickém sestavení vždy vytvořen s novým číslem verze. Obsahuje tedy jen řádek s AssemblyVersion atributem.

Při automatickém sestavení se mění číslo sestavení (Major.Minor.Build.Revision), přičemž číslo revize je nastaveno na 0. Pro vývojáře je v TFS repozitory je číslo revize nahrazeno znakem '*', takže vývojářské verze se liší od produkční. Informace o verzi jsou ukládány do souboru version.txt, který je součástí solution. V něm je možné měnit čísla verzí Major, Minor ručně a při dalším automatickém sestavení budou použity.

Jednotlivá automatická sestavení jsou pojmenována ve tvaru <jméno>_<verze>, místo výchozího pojmenování pomocí datumů.

Protože používám WiX pro vytváření instalátorů, tak je popsána i možnost verzování WiX projektů. A výsledkem celého snažení je pouze již hotový MSI balíček.

Co je potřeba

Celé je to postaveno tak, aby vývojářské PC nepotřebovalo žádné speciální nastavení. Takže všechno musí být na stroji, který provádí samotný build. Vlastně stačí jenom MSBuild Community Tasks.

A samozřejmě vytvořený Team Build. Na jeho jméně nezáleží, protože skoro všechno je vytvořeno variabilně. Co není, na to zvlášť upozorním.

Předpokládá se, že v adresáři solution jsou sobory version.txt a SolutionVersion.cs. Dále, že solution obsahuje WiX projekt s názvem "Setup", který obsahuje soubor version.template pro vytvoření souboru Version.wxi s verzí pro MSI balíček.

Jak to funguje

V před vlastním sestavením se stáhne z TFS repozitory soubor s poslední verzí. Tato verze se zvedne o 1. Následně se vytvoří soubory s verzemi pro jednotlivé projekty (cs soubor pro projekty v C# a wxi soubor, který je vložen do souboru pro WiX, ze kterého je vytvořen MSI balíček.

Po dokočení kompilací je v souboru cs provedena náhrada čísla revize a všechny vytvořené a změněné verzovací soubory jsou vráceny do TFS repozitory. Tím je zajištěno že všichni vývojáři budou mít nová čísla verzí.

Krok 1: Editace TFSBuild.proj

Celé nastavení automatického buildu je v souboru TFSBuild.proj, uloženém na serveru v adresáři TeamBuildTypes\<jméno buildu>. Tento soubor je vlastně msbuild projektový soubor, který build server vykoná.

Tento soubor je potřeba nejprve pomocí příkazu "Get latest version" stáhnout na lokální disk a pomocí "Check-out" uvolnit pro editaci a otevřít, klidně rovnou ve Visual Studiu, ale stačí i notepad.

Krok 2: Import MSBuild  Community Tasks

Aby fungovali přidané msbuild tasky, je nutné je do projektového souboru naimportovat. Najdeme tedy řádek. kde je proveden import Team Build tasků (najít řádek na kterém je tag "Import") a za něj přidáme nový:

  <Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" />

Krok 3: Cesta k tf.exe

Protože budeme potřebovat tahat soubory z Team Serveru a žádná rozumná cesta v msbuildu není, tak si pomůžeme spouštěním řádkového příkazu tf.exe. Cestu k tomuto příkazu zadáme někam mezi PropertyGroup:

<!-- TF.exe -->
<TF>&quot;c:\Program Files\Microsoft Visual Studio 8\Common7\IDE\TF.exe&quot;</TF>

Krok 4: Pojmenování sestavení

Na začátku cyklu sestavení se vytváří jméno sestavení. Toho je využito a nejen, že je jméno změněno na více popisné, než je výchozí, tak jsou také naplněny proměnné verzí. MSBuild target se jmenuje BuildNumberOverrideTarget.

<Target Name="BuildNumberOverrideTarget" Condition="'$(IsDesktopBuild)'!='true'">
 
    <MakeDir
        Directories="$(SolutionRoot)"
        Condition="!Exists('$(SolutionRoot)')" />
 
    <!-- Delete the workspace left by previous run -->
    <DeleteWorkspaceTask
        TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
        Name="$(WorkspaceName)" />
 
    <!-- Create the workspace enlistment -->
    <CreateWorkspaceTask
        TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
        MappingFile="$(WorkspaceMappingFile)"
        LocalPath="$(SolutionRoot)"
        Name="$(WorkspaceName)"
        TeamProject="$(TeamProject)" />
 
    <!-- Get the latest version source from the workspace -->
    <Get
        Condition=" '$(SkipGet)'!='true' "
        Workspace="$(WorkspaceName)"
        Recursive="$(RecursiveGet)"
        FileSpec="$(SolutionRoot)\Source\version.txt"
        Force="$(ForceGet)" />
 
    <!-- Workaround: Version task must have read/write access -->
    <Attrib Files="$(SolutionRoot)\Source\version.txt" ReadOnly="false" />
 
    <!-- Get setup build number -->
    <Version VersionFile="$(SolutionRoot)\Source\version.txt" 
        BuildType="Increment" RevisionType="BuildIncrement">
      <Output TaskParameter="Major" PropertyName="BuildVersionMajor" />
      <Output TaskParameter="Minor" PropertyName="BuildVersionMinor" />
      <Output TaskParameter="Build" PropertyName="BuildVersionBuild" />
      <Output TaskParameter="Revision" PropertyName="BuildVersionRevision" />
    </Version>
 
    <!-- Create BuildNumber property value, 
         if you want "better" default naming convetions
         you may delete it -->
    <CreateProperty Value="$(BuildType)_$(BuildVersionMajor).$(BuildVersionMinor).$(BuildVersionBuild).$(BuildVersionRevision)" >
      <Output TaskParameter="Value" PropertyName="BuildNumber" />
    </CreateProperty>
 
</Target>

Krok 5: Vytváření verzovacích souborů

Všechny změny v souborech vytvořených v BuildNumberOverrideTarget jsou přepsány v okamžiku kdy msbuild vytáhne kompletní zdrojové kódy pro překlad. Hned poté vytvoříme soubory s verzemi. SolutionVersion.cs se vytváří 2x. Nejprve s '*' místo revize a hned se všechno uloží zpět do TFS repozitory. Potom se revize nastaví na 0 se kterou je provedena kompilace.

<Target Name="AfterGet" Condition="'$(IsDesktopBuild)'!='true'">
 
    <!-- Check out version files -->
    <Exec Command="$(TF) checkout &quot;$(SolutionRoot)\Source\version.txt&quot; &quot;$(SolutionRoot)\Source\Setup\version.wxi&quot; &quot;$(SolutionRoot)\Source\SolutionVersion.cs&quot;" WorkingDirectory="$(SolutionRoot)" />
 
    <!-- Set file setup build number -->
    <WriteLinesToFile
       File="$(SolutionRoot)\Source\version.txt"
       Lines="$(BuildVersionMajor).$(BuildVersionMinor).$(BuildVersionBuild).$(BuildVersionRevision)"
       Overwrite="true" />
 
    <!-- Create tokens for wxi file replace -->
    <CreateItem Include="Major" AdditionalMetadata="ReplacementValue=$(BuildVersionMajor)">
      <Output TaskParameter="Include" ItemName="TokenMajor"/>
    </CreateItem>
    <CreateItem Include="Minor" AdditionalMetadata="ReplacementValue=$(BuildVersionMinor)">
     <Output TaskParameter="Include" ItemName="TokenMinor"/>
    </CreateItem>
    <CreateItem Include="Build" AdditionalMetadata="ReplacementValue=$(BuildVersionBuild)">
      <Output TaskParameter="Include" ItemName="TokenBuild"/>
    </CreateItem>
    <CreateItem Include="Revision" AdditionalMetadata="ReplacementValue=$(BuildVersionRevision)">
      <Output TaskParameter="Include" ItemName="TokenRevision"/>
    </CreateItem>
 
    <CreateItem Include="@(TokenMajor);@(TokenMinor);@(TokenBuild);@(TokenRevision)">
      <Output TaskParameter="Include" ItemName="Tokens"/>
    </CreateItem>
 
    <!-- Replace tokens and create version.wxi -->
    <TemplateFile Template="$(SolutionRoot)\Source\Setup\Version.template" 
        OutputFilename="$(SolutionRoot)\Source\Setup\Version.wxi" 
        Tokens="@(Tokens)" />
 
    <!-- Solution version file, change CodeLanguage for VB -->
    <AssemblyInfo CodeLanguage="CS"
        OutputFile="$(SolutionRoot)\Source\SolutionVersion.cs"
        AssemblyVersion="$(BuildVersionMajor).$(BuildVersionMinor).$(BuildVersionBuild).*" />
 
    <!-- Check in version files -->
    <Exec Command="$(TF) checkin &quot;$(SolutionRoot)\Source\version.txt&quot;  &quot;$(SolutionRoot)\Source\Setup\version.wxi&quot; /comment:&quot;Setup version $(BuildVersionMajor).$(BuildVersionMinor).$(BuildVersionBuild)&quot; &quot;$(SolutionRoot)\Source\SolutionVersion.cs&quot; /noprompt /override:BUILDSERVER " WorkingDirectory="$(SolutionRoot)" />
 
    <!-- Workaround: Version task must have read/write access -->
    <Attrib Files="$(SolutionRoot)\Source\SolutionVersion.cs" 
        ReadOnly="false" />
    <!-- Now generate version file with Revision = 0 -->
    <AssemblyInfo CodeLanguage="CS"
        OutputFile="$(SolutionRoot)\Source\SolutionVersion.cs"
        AssemblyVersion="$(BuildVersionMajor).$(BuildVersionMinor).$(BuildVersionBuild).$(BuildVersionRevision)"
        AssemblyFileVersion="$(BuildVersionMajor).$(BuildVersionMinor).$(BuildVersionBuild).$(BuildVersionRevision)" />
 
</Target>

Krok 6: Zabalení výsledků kompilace

Nepovinný krok, pouze pro jistotu zabalím všechny *.dll, *.pdb do zipu a smažu je, potřebujeme jenom MSI balíček. Vlastně je ani balit nemusím a rovnou je smazat. Build server potom všechno přesune do cílového adresáře. A to je vlastně vše.

<Target Name="PackageBinaries"
    Condition="'$(IsDesktopBuild)'!='true'">
 
    <!-- Zip and delete assemblies (without MSI) -->
    <CreateItem Include="$(OutDir)\**\*.*" Exclude="$(OutDir)\**\*.msi">
      <Output ItemName="FilesToDelete" TaskParameter="Include" />
    </CreateItem>
 
    <!-- package (you may remove this line and simply delete files) ... -->
    <Zip Files="@(FilesToDelete)" WorkingDirectory="$(OutDir)" 
        ZipFileName="$(OutDir)\$(BuildNumber).zip" />
 
    <!-- ... and delete -->
    <Delete Files="@(FilesToDelete)" />
 
</Target>

Soubory

Protože všechny zmíněné soubory musí existovat, je nutno je vytvořit:

  • version.txt
1.0.0.0
  • SolutionVersion.cs
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
 
[assembly: AssemblyVersion("1.0.0.*")]
  • version.template
<?xml version="1.0" encoding="utf-8"?>
<Include>
    <?define ProductMajor = "${Major}" ?>
    <?define ProductMinor = "${Minor}" ?>
    <?define ProductBuild = "${Build}" ?>
    <?define ProductRevision = "${Revision}" ?>
    <?define ProductVersion = "${Major}.${Minor}.${Build}" ?>
</Include>
  • version.wxi
<?xml version="1.0" encoding="utf-8"?>
<Include>
    <?define ProductMajor = "1" ?>
    <?define ProductMinor = "0" ?>
    <?define ProductBuild = "0" ?>
    <?define ProductRevision = "0" ?>
    <?define ProductVersion = "1.0.0" ?>
</Include>

Trocha WiXu na závěr

Jen malá ukázka jak potom vypadá wxs soubor. Je to jenom začátek ...

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
 
    <?include Version.wxi ?>
 
    <Product Id="*" Name="Program $(var.ProductVersion)" 
             Language="1033"
            Version="$(var.ProductVersion)" Manufacturer="Me"
            UpgradeCode="{AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAA0}">
        <Package InstallerVersion="200" Compressed="yes" />
 
        <Upgrade Id='{AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAA1}'>
            <UpgradeVersion OnlyDetect='yes' Property='PATCHFOUND'
              Minimum='$(var.ProductVersion)' IncludeMinimum='yes' 
              Maximum='$(var.ProductVersion)' IncludeMaximum='yes' />
            <UpgradeVersion OnlyDetect='yes' Property='NEWERFOUND'
              Minimum='$(var.ProductVersion)' IncludeMinimum='yes' />
            <UpgradeVersion OnlyDetect='no' Property='UPGRADE'
              Maximum='$(var.ProductVersion)' IncludeMinimum='no'/>
        </Upgrade>
...atd
Posted by arci | 2 Comments
Vedeno pod: ,

Náhrada SQL Server Agent v Express edici

 

SQL Agent - A Job Scheduler Framework je služba umožňující nahradit chybějícího agenta. Jediná nevýhoda je (nebo je to výhoda?), že jednotlivé úlohy jsou psány jako pluginy v C# nebo VB.Net 2005.

Poznámka: Tohle jsem už jednou psal, ale příspěvek odešel do věčných a nekonečných plání velkého prapůvodního disku.

Posted by arci | 0 Comments
Vedeno pod:

Nikdy nedělej nic na poslední chvíli.

Když už všichni píšou o blbostech cizích, tak já něco o té vlastní.

V pátek jsem poslal do několika zařízení aktualizaci. Bylo po pracovní době a tak už nebyl čas otestovat výsledek. Program je samozřejmě v pořádku, bohužel jsem zařízením odeslal špatnou konfiguraci, která je připojila na testovací server místo produkčního. A protože neštěstí nechodí samo, tak lidi přišli do práce o víkendu, aby si něco dodělali.

Posted by arci | 0 Comments
Vedeno pod:

Pár poznámek pro Compact Framework 2.0

Design-time support

Jak přidat design-time support a zbavit se prázdného obdélníku v designeru při vytvážření vlastních ovládacích prvků je popsáno v článku "Compact Framework Custom Control Design Support in Visual Studio 2005"

Užitečné odkazy na ovládací prvky

Smart device Framework (SDF) od OpenNETCF je snad základ.

Bindable ListView for .NetCF je užitečná věcička, která může v některých případech nahradit i DataGrid.

Chyba genasm

Při použití výše uvedeného postupu je možné dostat následující chybovou hlášku:

genasm.exe(1) : error There was an error finalizing type. 
Type 'MyNameSpace.MyClass, MyLibrary, Version=1.0.0.0, 
Culture=neutral, PublicKeyToken=null' was loaded 
in the ReflectionOnly context but the AssemblyBuilder 
was not created as AssemblyBuilderAccess.ReflectionOnly.

případně obměnu (liší se jedním slovem):

genasm.exe(1) : error There was an error initializing type. 
Type 'MyNameSpace.MyClass, MyLibrary, Version=1.0.0.0, 
Culture=neutral, PublicKeyToken=null' was loaded 
in the ReflectionOnly context but the AssemblyBuilder 
was not created as AssemblyBuilderAccess.ReflectionOnly.

Popis důvodů a řešení je tady. Dělá to spojení design-time supportu a public potomek generického listu. Ale zjistil jsem, že je lepší tyhle dvě věci v jedné assembly vůbec nemíchat, nebo rovnou použít workaround.

Posted by arci | 0 Comments
Vedeno pod: ,

Registrace komponent do GAC při instalaci

Před nějakou dobou jsem řešil, jak při instalaci zaregistrovat komponenty do GAC místo ponechání u nainstalované aplikace. Napadlo mě komponenty zabalit do archivu zipem a při instalaci je pomocí Custom Install Action rozbalit do dočasného umístění, zaregistrovat a smazat. Na disku po dokončení instalace zůstane jen zabalený archiv.

Pro rozbalení zip archivu je použita knihovna #ziplib, jejíž licence umožňuje použití i v komerčních projektech. Navíc, protože jsem potřeboval instalovat lokalizace, umožňuje archiv jednu úroveň adresářů, kde se předpokládají lokalizované resource assembly.

Všechno platí pro Visual Studio 2003.

Krok 1

K vytvoření vlastní instalační akce stačí vytvořit potomka třídy System.Configuration.Install.Installer a nastavit atribut RunInstallerAttribute na true, jinak nebude akce spuštěna.

[RunInstaller(true)]
public class CustomInstaller : Installer
{
  public CustomInstaller() : base()
  {		
  }

  /// 
  /// On install action
  /// 
  /// 
  public override void Install(System.Collections.IDictionary stateSaver)
  {
    base.Install(stateSaver);
    // Vlastní instalační akce
  }

  /// 
  /// On uninstall action
  /// 
  /// 
  public override void Uninstall(System.Collections.IDictionary savedState)
  {
    base.Uninstall(savedState);
    // Similar as instal, use p.GacRemove(...);
  }
}

Krok 2

Manipulace s archivem zip pomocí #ziplib je jednoduchá. Stačí použít třídu FastZip.

  FastZip zFile = new FastZip();
  zFile.ExtractZip(zipFileName, tempPath, FastZip.Overwrite.Always, null, "", "");				

Krok 3

K registrace assembly do GAL je možné použít řádkovou utilitu gacutil.exe nebo třídu Publish z namespace System.EnterpriseServices.Internal.

  Publish p = new Publish();
  p.GacInstall(fileName);

Krok 4

Přiložit do instalace assembly, ve které je vlastní akce a soubor s archivem zip, samozřejmě i ICSharpCode.SharpZipLib.dll. Třeba do zvláštního adresáře.

Takhle to vypadá ve studiu

Krok 5

Nastavit spouštění akce při událostech instalace.

Takhle to vypadá ve studiu

A je to hotovo ...

Zdrojové soubory ukázkové aplikace najdete tady. Instalátor do GAC zaregistruje ICSharpCode.SharpZipLib.dll, která je obsažena v archivu InstallGAC.zip

Postupem doby mě napadla ještě další vylepšení

  1. Možnost zadat jméno archivu do Setup projektu.
  2. Možnost instalovat komponenty z více archivů.
  3. Použít jiný formát, třeba CAB, pro který není nutná další knihovna.
Posted by arci | 0 Comments

String resource generator pro VS2003

Jen jako poznámku, pro ty co ještě používají VS2003 a líbí se jim myšlenka generování resources lepším způsobem než ručním psaním např. podobně jako to dělá Microsoft Enterprise Library, tak tady to je.

Posted by arci | 0 Comments
Vedeno pod:
Více článků Další stránka »
 
Vyvojar.cz na prodej!