MSBuild v rámci TFS Build Service nevytváří Web Deployment Packages

Problém

V projektu máme webovou aplikaci, která má Publish Profile, který má vytvořit Web Deployment balíček. Balíček se úspěšně vytváří jak při spuštění MSBuildu z Visual Studia, tak z příkazové řádky na vývojářském počítači, tak při spuštění z příkazové řádky na počítači s TFS Build Service. Jenže při spuštění z TFS Build Service se balíček nevytvoří.

Proč to nefunguje

Podoba publish profile, který byl vyroben pomocí UI ve Visual Studio 2013 je (plus mínus) takováto:

<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebPublishMethod>Package</WebPublishMethod>
<DesktopBuildPackageLocation>TfsPublish\BalicekKteryChciVytvorit.zip</DesktopBuildPackageLocation>
<PackageAsSingleFile>true</PackageAsSingleFile>
...
</PropertyGroup>
</Project>

Důvodem, proč se balíček nevytváří je skutečnost, že Visual Studio do publish profilu vytvoří vlastnost DesktopBuildPackageLocation, jenže je očekávána hodnota vlastnosti PackageLocation.

A jak to, že v rámci VS a z příkazové řádky to funguje? Protože PackageLocation se v průběhu načítání C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\Web\Microsoft.Web.Publishing.targets nastaví podle DestopBuildPackageLocation.

<PackageLocation Condition="'$(PackageLocation)'=='' and !(('$(OutDir)' != '$(OutputPath)') Or ('$(IsDesktopBuild)' == 'False')) ">$(DesktopBuildPackageLocation)</PackageLocation>

Jenže jen za podmínky, kdy IsDesktopBuild není false (druhou podmínku není ukázanou výše třeba řešit). Otázkou je, kde se nastavuje hodnota vlastnosti IsDesktopBuild. Odpověď se skrývá v témže souboru:

<IsDesktopBuild Condition="'$(IsDesktopBuild)'=='' And '$(TeamFoundationServerUrl)' != ''">False</IsDesktopBuild>

A problém je objasněn – TFS Build Service nastavuje hodnotu TeamFoundationServerUrl, čímž se build liší od spuštění z příkazové řádky.

Možnosti řešení

Nastavení vlastnosti PackageLocation bohužel nefunguje v rámci vlastního targetu, neboť to je již pozdě. Z vlastnosti se odvozují další vlastnosti během načítání target souborů.

  1. Natvrdo nastavit hodnotu IsDesktopBuild na True při spouštění MS Buildu. Nenašel jsem žádné jiné použití této vlastnosti, tedy alespoň prozatím jde o bezpečné řešení.
  2. Během studia zmíněného souboru s MSBuild targety jsem našel, že se MSBuild po importu PublishProfile souboru (pubxml) pokouší importovat ještě další targety, pokud existují. Šlo by tedy takový soubor vytvořit a v něm zkopírovat hodnotu z DesktopBuildPackageLocation do PackageLocation.
    Pokud se projekt jmenuje Web a ten obsahuje publish profile v Properties\PublishProfiles\TfsPublish.pubxml, pak se načítají
  • Web\Properties\PublishProfiles\TfsPublish.wpp.targets (viz vlastnost WebPublishProfileCustomizeTargetFile)
  • Web\*.wpp.targets (viz vlastnost WebPublishPipelineCustomizeTargetFile)
  • Web\..\wpp.deploysettings.targets (viz WebPublishPipelineSolutionTargetFile)

Advanced .NET Debugging – záznam, slides a dema [MS Fest Brno 2014]

Slides z mé přednášky 18.10.2014 pro konferenci MS Fest Brno:

Z přednášky jsem pořizoval záznam, který najdete na našem HAVIT YouTube Channelu:

Základní algoritmy v praxi [MS Fest Brno 2014]

Slides z mé přednášky 18.10.2014 pro konferenci MS Fest Brno:

Z přednášky jsem pořizoval záznam, který najdete na našem HAVIT YouTube Channelu:

Perly code-review z praxe – záznam a slides [MS Fest Brno 2014]

Slides z mé přednášky 18.10.2014 pro konferenci MS Fest Brno:

Z přednášky jsem pořizoval záznam, který najdete na našem HAVIT YouTube Channelu:

Prohlížeč fotografií Windows zobrazuje obrázky s výrazným barevným posunem

Barvy obrázků mohou být posunuty do různých barev, obvykle do žluta, do červena, do růžova nebo něco mezi tím.

Problém nejspíš spočívá v chybné interpretaci barevných profilů. Pokud barevné profily k ničemu nepoužíváme, můžeme je odebrat a použít profil sRGB. Tím je problém vyřešen a prohlížeč fotografií zobrazuje obrázky čistě.

2014-10-17_1034

 

Copy–Paste a nechtěné mezery ve formulářích

Ve formulářovém poli chceme po uživateli e-mailovou adresu nebo třeba nový login name – jaké je jeho rozčarování, když po vložení adresy pomocí CTRL-V (zkopírované např. z Excelu), aplikace hlásí
nevalidní údaj.
Na vině jsou nechtěné mezery připojené za (a někdy i před) adresu.
Nechtěné mezery nám pomůže odstranit funkce aktivovaná událostí input -> na oninput řetězec trimujeme.
Provedeme to pouze, pokud se otrimovaný a původní řetězec liší (tj. je co trimovat) – pokud bychom to dělali bez této podmínky, tak vždy, když by uživatel ručně vepsal nějaký znak, skočil by mu kurzor v políčku na konec pole (i tehdy, pokud by něco editoval uprostřed textu).

if (formField.value != formField.value.trim())
{
    formField.value = formField.value.trim();
}

Pro ASP.NET si můžeme vytvořit takovýto skin:

<asp:TextBox SkinID="TrimOnInput" oninput="if (this.value!=this.value.trim()) {this.value=this.value.trim();};" runat="server" /> 

Funkce se nehodí pro pole, která mají obsahovat mezeru mezi slovy (např. „Jan Novák“) – i když takové celé jméno lze do pole vložit pomocí CTRL-C, zcela určitě nebude možné jméno pohodlně napsat – pole se totiž chová tak, že na stisk mezerníku za slovem nereaguje.

Azure WebSites – rozcestník pro počáteční orientaci

Nejprve jsem myslel, že to dám k nám na interní wiki, ale mohlo by se to hodit i dalším…

Domain Catch-all – pokračování

Pár měsíců nazpět jsem si tu zoufal (Domain Catch-all) při neúspěšných pokusech o nastavení doménového koše pro jednu z našich domén, kterou používáme na příjem testovacích emailů, které během vývoje produkují naše aplikace. Cílem bylo aby jakýkoliv email který je odeslán na emailovou adresu *@devmail.havit.cz došel do konkrétní schránky. Tenkrát se ještě nezadařilo, neboť Exchange tvrdošíjně odmítal přijmout jakékoliv zprávy určené uživatelům které neznal a pravidlo se tak nemohlo uplatnit. To už je ale minulostí, problém se podařilo vyřešit.

Stačilo nastavit v menu mail flow v záložce accepted domains pro danou doménu s pravidlem Domain cach all volbu Internal Relay: Email is delivered to recipients in this Exchange organization or relayed to an email server at another physical or logical location.

Nastavení accepted domains pro Domain catch all pravidlo

Nastavení accepted domains pro Domain catch all pravidlo

Od té doby funguje všechno jak má. Naštěstí nemusíme řešit situaci kdybychom chtěli podobné chování pro naši regulérní doménu havit.cz.

Stránky která se tématu věnuje do větší hloubky: Catch-All for MS Exchange 2013 SP1 on specific Authoritative Domains – Server Fault

Automatické ukončování odpojených RDP session po určité době

Na Terminal Services lze nastavit, aby se odpojené (disconnected) session automaticky ukončily:

  1. Control Panel ~ Administrative Tools
    ~ Terminal Services ~ Terminal Services Configuration (do Windows Server 2008).
    ~ Remote Desktop Services ~ Remote Desktop Session Host Configuration (od Windows Server 2008 R2)
  2. Right-Click na RDP-Tcp + Properties (nebo double-click, je to default akce).
  3. Záložka Session, volba End a disconnected session:image

Pozor, že se jedná opravdu o tvrdé nevybírané ukončení session, takže se to nebude mazat s žádnou neuloženou rozpracovanou úlohou, běžícím Profilerem/Debuggerem/Fiddlerem nebo čímkoliv podobným.

Windows Explorer: Založení/přejmenování souboru s názvem začínajícím tečkou

Pokud potřebujete vytvořit nebo přejmenovat ve Windows Exploreru soubor/složku na jméno, které začíná tečkou (.tfignore, .svn, …), funguje jednoduchý trik – přidejte ještě jednu tečku na konec jména(např. „.tfignore.“). Windows Explorer to překousne a záměru je dosaženo.

…starý trik, ale občas si ho musím připomenout.