Před pár dny přestal správně pracovat můj noční build jedné aplikace Dynamics AX 2009. V sestavené vrstvě chyběly některé objekty, což pochopitelně způsobilo spoustu kompilačních chyb.
Ukázalo se, že data byla v pořádku získána ze správy verzí, ale aplikace Combine XPO Tool (CombineXPOs.exe) je nedokázala zpracovat. (Pokud ji neznáte, Combine XPO se používá k sloučení více .xpo souborů do jednoho – typicky (jako v tomto případě) ke zkombinování všech souborů získaných ze správy verzí před importem do AX.)
CombineXPOs.exe vrátila návratový kód -4 a zapsala následující chybovou zprávu do standardního výstupního proudu:
Error [-4] The file is bad: C:\NightBuild\SourceFiles\bus\Data Dictionary\Tables\AddressCountryRegion.xpo. Exception message: System.ArgumentOutOfRangeException: Length cannot be less than zero. Parameter name: length
V překladu to znamená toto:
Chyba [-4] Soubor je špatný: C:\NightBuild\SourceFiles\bus\Data Dictionary\Tables\AddressCountryRegion.xpo. Chybová zpráva: System.ArgumentOutOfRangeException: Délka nesmí být menší než nula. Jméno parametru: length
Jak můžete očekávat, Combine XPO nezpracovala zbývající soubory, tudíž sloučený .xpo soubor byl nekompletní. Druhá část problému byla v tom, že návratový kód nebyl v sestavovacím skriptu ošetřen.
Ono problematické .xpo obsahovalo toto:
Exportfile for AOT version 1.0 or later Formatversion: 1 ***Element: END
Jak můžete vidět, neobsahuje téměř nic – dokonce ani typ a jméno objektu. A Combine XPO není jediný nástroj, který má s takovým .xpo problémy – porovnání verzí v AX2009 vyhodilo na tomto objektu runtime chybu (zdá se, že v AX2012 to funguje bez problémů).
Verze Combine XPO Tool
Když jsem toto chování testoval, všiml jsem si, že různé verze Combine XPO Tool řeší tuto situaci odlišně:
Verze 1.0.3974.781 (to je verze dostupná na blogu mfp a ta kterou jsem používal v nočních buildech)
Výsledek | Zpracování zastaveno na poškozeném .xpo souboru |
Návratový kód | -4 |
Standardní výstup | Error [-4] The file is bad: C:\NightBuild\SourceFiles\bus\Data Dictionary\Tables\AddressCountryRegi on.xpo. Exception message: System.ArgumentOutOfRangeException: Length cannot be less than zero. Parameter name: length |
Version 6.0.947.5121 (stažena z InformationSource; oficiální název Microsoft Dynamics AX 2012 Combine XPO Tool Beta 1.0):
Result | Zpracovány všechny soubory |
Exit code | -4 |
Standardní výstup | 1764 XPO files processed Ok |
Standard error | CombineXPOs.exe : Warning [-5] CombineXPOs.exe : Error [C:\NightBuild\SourceFiles\bus\Data Dicti onary\Tables\AddressCountryRegion.xpo] Length cannot be less than zero. Parameter name: length |
Obě verzi si stěžují na poškozené .xpo, ale ta novější ho zkrátka přeskočí a pokračuje, ta starší se zastaví a vy dostanete .xpo, které nezahrnuje obsah všech vstupních .xpo souborů. Někdo si toho problému asi všiml a to chování změnil. Jedna zajímavá věc je to, že obě verze vrací zcela stejný návratový kód.
Jak vytvořit poškozené .xpo
Vytvoření poškozeného .xpo je překvapivě jednoduché. Například můžete následovat tyto kroky:
- Najděte tabulku, která existuje v nižší vrstvě (třeba SYS), ale ne ve vaší vývojové vrstvě.
- Přidejte nové pole.
- Vložte objekt do zprávy verzí.
- Proveďte check in.
- Proveďte check out.
- Odeberte pole.
- Opět proveďte check in.
V bodě 7 v zásadě ukládáte do správy verzí objekt, který už ve vývojové vrstvě neexistuje, protože jste všechny změny (jedno pole) odebrali. AX pak vyexportuje všechny změny (= žádné), čímž vznikne prázdné .xpo popsané výše (testováno v AX2009 + SourceSafe a AX2012 R2 + TFS).
Tato procedura není to, co byste měli použít – chcete-li odebrat všechny změny, fakticky odstraňujete daný objekt, tudíž byste ho měli skutečně odstranit a smazání uložit do správy verzí (smazání je prostě jeden z typů akce ve správě verzí).
Jak zpracovat návratový kód z Combine XPO
Pokud by byl návratový kód řádně zpracován, problém by nezmizel – ale bylo by očividné, co je špatně.
Protože nová verze Combine XPO zkrátka přeskočí poškozená .xpo, můžete mít tendenci celý problém ignorovat. Ale to není správný přístup, protože existují i další důvody proč může Combine XPO selhat. Například pokud zdrojový adresář neexistuje, obdržíte návratový kód -2.
Byla by také chyba ignorovat návratový kód -4 – ten dostanete pro jakoukoli výjimku v jedné části Combine XPO, není nijak svázán s tímto konkrétním problémem.
Mohli byste analyzovat zprávy zapsané do chybové výstupního proudu, ale nejjistější je zastavit zpracování pokaždé, kdy návratový kód není roven nule.
Ukázku najdete v následujícím Powershellovém kódu. Pracuje s oběma verzemi Combine XPO (hledá chybová hlášení jak v chybovém, tak standardním výstupu) a také zpracovává návratové kódy bez chybové zprávy. Kód jednoduše vyhazuje výjimku, protože všechny výjimký jsou zpracovány buildovacím skriptem pomocí příkazu trap
(ten zde není ukázán).
$output = & $combineXpoExe -XpoDir $sourceFilesDir -CombinedXpoFile $combinedFile -utf8 2>&1 if ($LastExitCode -ne 0) { $err = "CombineXPOs.exe: Exit code $LastExitCode" if ($output) { $err = $output | ?{$_.getType().Name -eq "ErrorRecord"} if (!$err) { $err = $output } } throw $err }