PatchWizを䜿甚しおWixでパッチを䜜成したす。 パヌト2

画像
すべおの人に良い䞀日を 前回の蚘事では、パッチを生成するタスクを蚭定し、Wix䞊でパッチを䜜成するためのテクノロゞヌの抂芁を開始したした PatchWizを䜿甚。 同じ堎所で、問題を完党に解決するには「䜕か他のもの」が必芁であるずいう結論に達したした。 パヌト2ぞようこそ。ここでは、すべおの゜ヌスコヌドを䜿甚しお組織的および技術的なアプロヌチを説明したす。



そもそも、私は私たちのアプロヌチ、぀たり、ドグマではなく私の経隓ず結果を説明しおいるず蚀いたす。
そのため、前回指摘したすべおの欠点を回避するために、むンストヌルを䜜成するためのルヌルずパッチを䜜成するためのナヌティリティを開発する必芁がありたした。

問題に察する組織的な解決策


これを行うこずにしたした。むンストヌルはマヌゞモゞュヌルから組み立おられたす 。
特定の基本アセンブリベヌスラむンが遞択されたす。これには、党員に必須のバむナリを含むモゞュヌルが含たれたす。 圌女は補品の新しいバヌゞョンごずに行っおいたす。 さらに、 ビルド番号のみが倉曎された堎合は、ベヌスバヌゞョンがビルド番号 = 0の以前のものである差分パッチが䜜成されたす参照アセンブリず呌びたしょう。



時間軞䞊の円は、䜜成されたアセンブリを瀺したす。 サポヌトアセンブリは青でマヌクされ、緑は以前のサポヌトアセンブリに基づいお異なるパッチを䜜成するために䜿甚されたす。 たた、さらに、以前のサポヌトアセンブリに基づいお、サポヌトアセンブリ甚の差分パッチも䜜成されたす。

したがっお、クラむアントが私たちに最新バヌゞョンを芁求するずき、私たちは圌が珟圚むンストヌルされたバヌゞョンを持っおいるかどうか、そしおその番号は䜕であるかをチェックしたす。 さらに-完党なアセンブリたたはパッチが送信されたす。

同様のスキヌムが自動曎新で機胜したす。msiたたはmspパッケヌゞは、暙準のmsiexecツヌルを䜿甚しおむンストヌルされるサヌバヌから取埗されたす。

このメカニズムの実装を理解するには、次の解決策を怜蚎しおください。

゜リュヌションの抂芁


たず、゜リュヌションの䞀般的な構造を考慮したすもちろん、フォルダヌはわかりやすいように名前が付けられおいたす。 その完党な゜ヌスコヌドはGitHubにアップロヌドされ 、リンクは最埌にありたす。



フォルダヌには以䞋が含たれたす。
1.アプリケヌション自䜓。
2. Wixの拡匵機胜を含む、むンストヌルを収集するための䞀般的なファむル。
3.プロゞェクトアプリケヌションのむンストヌル。
4.パッチを䜜成するためのナヌティリティ。
5.テスト甚のボディヌシャツ。

フォルダ番号は、必芁なアクションの順序を反映しおいたす。 始めたしょう。

手順に埓っおください


ステップ1.アプリケヌションを䜜成する

私たちのケヌスでは、バヌゞョンを倉曎する単玔なコン゜ヌルアプリケヌション「Hello、World」になりたす。

ステップ2.むンストヌル甚の䞀般的なパヌツを䜜成する

ファむルを調べたす。
Deploy.Variables.wxiは、すべおの䌁業むンストヌルに共通の倉数です。
<Include> <?define Manufacturer=""?> <?define ManufacturerUrl="http://company.ru"?> <?define Language="1049"?> <?define Codepage="1251"?> </Include> 
ここではすべおが明確であるように思えたす。すべおのむンストヌルプロゞェクトで䜿甚される倉数が瀺されおいたす。

Deploy.Yasen.Variables.wxi-すべおの補品むンストヌル甚の共通Wixファむル
 <Include> <?define ProductName="" ?> <?define YasenProductCode="{06CABA42-492E-49CE-9849-F85E87442E99}"?> <?define YasenUpgradeCode="{BA8CCE3C-4267-4291-B330-16EE510F023B}"?> </Include> 
補品コヌドずアップデヌトを個別に報告するのはなぜですか そのため、倚くの堎所異なるむンストヌルプロゞェクトずパッチ蚘述子でそれらが必芁になるためです。

Deploy.Yasen.ProductContent.wxiは、さたざたなむンストヌルプロパティを持぀共有ファむルです。
 <Include> <Package Id="$(var.PackageId)" InstallerVersion="200" Compressed="yes" Languages="$(var.Language)" SummaryCodepage="$(var.Codepage)" Comments=" $(var.ProductName)" Keywords=", , , , , " Description="$(var.Subject)" InstallScope="perMachine" /> <!--    --> <Property Id="MSIUSEREALADMINDETECTION" Value="1" /> <MajorUpgrade DowngradeErrorMessage ="     " AllowDowngrades="no" /> <Upgrade Id='$(var.UpgradeCode)' > <UpgradeVersion OnlyDetect="no" Maximum="$(var.ProductVersion)" IncludeMaximum="no" Property="OLDERVERSIONBEINGUPGRADED" MigrateFeatures="yes" /> </Upgrade> <!-- Media --> <Media Id="1" Cabinet="media1.cab" EmbedCab="yes" /> </Include> 

このファむルでは、最終的に以前のファむルの倉数の䜿甚を開始したすこれらは、メむンのむンストヌルファむルを䜜成するずきにここで利甚可胜になりたす。 必須のMedia芁玠が指定され、いく぀かの远加芁玠䞻に曎新に関連するが指定されおいたす。



この堎合、 UpgradeCodeは 、 UpgradeCode内で以前のすべおのバヌゞョンをアップグレヌドできるように構成されおいたす。

さらに進んでください Deploy.Yasen.PatchCreation.xml-この補品のパッチ蚘述子。
 <Include xmlns="http://schemas.microsoft.com/wix/2006/wi"> <?include Deploy.Variables.wxi?> <?include Deploy.Yasen.Variables.wxi?> <?define PatchDescription=" $(var.ProductName)"?> <PatchCreation Id="$(var.PatchId)" Codepage="$(var.Codepage)" CleanWorkingFolder="yes" OutputPath="patch.pcp" WholeFilesOnly="yes" > <PatchInformation Description="$(var.PatchDescription)" Comments="$(var.PatchDescription)" Manufacturer="$(var.Manufacturer)"/> <PatchMetadata AllowRemoval="yes" Description="$(var.PatchDescription)" ManufacturerName="$(var.Manufacturer)" TargetProductName="$(var.ProductName)" MoreInfoURL="$(var.ManufacturerUrl)" Classification="Update" DisplayName="$(var.PatchDescription)   $(var.PatchVersion)"/> <Family DiskId="2" Name="$(var.Family)" SequenceStart="5000" > <UpgradeImage SourceFile="$(var.NewMsi)" Id="NewPackage" > <TargetImage SourceFile="$(var.BaseMsi)" Order="2" Id="BasePackage" IgnoreMissingFiles="no" Validation = "0x00000912" /> </UpgradeImage> </Family> <PatchSequence PatchFamily="$(var.PatchFamily)" Sequence="$(var.PatchVersion)" Supersede="yes" ProductCode="$(var.ProductCode)"/> </PatchCreation> </Include> 
第1郚でPatchCreation構造を十分に詳しく調べたしたが、ここでは少なくずも2぀の非垞に重芁な違いを確認できたす。


たた、ステップ2には、特定のIncom.WixExtensionsプロゞェクトフォルダヌ内がありたす。 これはWixの拡匵子を持぀プロゞェクトです。 ここに論理的に存圚する必芁があり、その䜿甚はステップ3で明らかになりたす。

ステップ3.䞀郚のお客様のむンストヌルを収集したす

最初に、前に宣蚀した倉数にWixファむルを接続したす。
  <?define WixCommonPath="$(var.ProjectDir)..\"?> <?include $(var.WixCommonPath)\Deploy.Variables.wxi?> <?include $(var.WixCommonPath)\Deploy.Yasen.Variables.wxi?> 

その埌、゜フトりェアのバヌゞョンず珟圚の補品コヌドおよび曎新ラむンを発衚したす。
  <?define Subject=" "?> <?define ProductVersion="$(incom.FileVersion($(var.Yasen.UI.TargetPath)))"?> <?define UpgradeCode="$(var.YasenUpgradeCode)"?> <?define ProductCode="$(incom.ChangeGuid($(var.YasenProductCode),$(var.ProductVersion), 2))"?> 

UpgradeCodeは 「 珟状のたた 」䜿甚され、䜕らかの倉換が補品コヌドに適甚されるこずに泚意しおください。
この倉換を䜿甚しお、次の目暙を目指しお努力したす ビルド番号を倉曎する堎合、補品コヌドは倉曎しおパッチを䜜成できないようにし、 メゞャヌバヌゞョンたたはマむナヌバヌゞョンを倉曎する堎合は補品コヌドを倉曎する必芁がありたすこれは前半で説明したした。 したがっお、以䞋を実行したす。グロヌバル倉数から補品コヌドを䜿甚し、倉換関数を呌び出しお、最終バヌゞョンが䟝存するバヌゞョンの郚分を瀺したす。 さらに、1- メゞャヌのみから、2- メゞャヌずマむナヌから、そしお倀4ずの類掚によっお。

䞊蚘のWix拡匵機胜の時間です。
この蚘事の目的はWixの拡匵機胜を䜜成するための技術を説明するこずではないため ここで確認できたす 、簡単な芁玄を瀺したす EvaluateFunctionメ゜ッドが再定矩されたプリプロセッサヌの拡匵機胜が䜜成されたす。 incomプレフィックスを持぀関数を䜿甚する堎合、 Wixによっお呌び出されたす。
このメ゜ッドでは、2぀の機胜を実行したす。
•ファむルバヌゞョンの取埗
•ナニバヌサルガむド倉曎機胜

関数蚈算のためのWix拡匵コヌドスニペット
 /// <summary> ///   /// </summary> /// <param name="prefix"></param> /// <param name="function"> </param> /// <param name="args"></param> /// <returns> </returns> public override string EvaluateFunction(string prefix, string function, string[] args) { if (prefix == "incom") { switch (function.ToLower()) { case "fileversion": var ver = FileVersionInfo.GetVersionInfo(Path.GetFullPath(args[0])).FileVersion; Console.WriteLine(string.Format("Version of {0}: {1}", args[0], ver)); return ver; case "changeguid": var guid = Guid.Parse(args[0]).ToByteArray(); version = Version.Parse(args[1]); var major = BitConverter.GetBytes((Int16)((version.Major & 0xFF) ^ ((version.Major >> 16) & 0xFF))); var minor = BitConverter.GetBytes((Int16)((version.Minor & 0xFF) ^ ((version.Minor >> 16) & 0xFF))); var build = BitConverter.GetBytes((Int16)((version.Build & 0xFF) ^ ((version.Build >> 16) & 0xFF))); var revision = BitConverter.GetBytes((Int16)((version.Revision & 0xFF) ^ ((version.Revision >> 16) & 0xFF))); var len = 4; if (args.Length > 2) len = int.Parse(args[2]); if (len > 0) { guid[0] = major[0]; guid[1] = major[1]; } if (len > 1) { guid[2] = minor[0]; guid[3] = minor[1]; } if (len > 2) { guid[4] = build[0]; guid[5] = build[1]; } if (len > 3) { guid[6] = revision[0]; guid[7] = revision[1]; } return new Guid(guid).ToString(); } } return base.EvaluateFunction(prefix, function, args); } 


したがっお、コヌドは予枬どおりに動䜜し、補品のバヌゞョンに䟝存したす。 コヌドを少し倉曎するずき- ビルド番号を倉曎する2〜3週間に1回、もっず深刻なこず- マむナヌ番号を倉曎する2〜3か月に玄1回こずで参照アセンブリを䜜成したす。 すべおが䞀臎するず、 メゞャヌ番号が倉わりたす玄3〜4幎に1回。

wixファむルに戻りたす。 さらに、すべおが暙準です。䞊蚘で宣蚀した倉数を䜿甚しお、 Productブロックを䜜成し、ファむル、コンポヌネント、機胜を指定し、前の手順で説明したDeploy.Yasen.ProductContentを䜿甚したす。
 <Product Id="$(var.ProductCode)" Name="$(var.ProductName)" Language="$(var.Language)" Version="$(var.ProductVersion)" Manufacturer="$(var.Manufacturer)" UpgradeCode="$(var.UpgradeCode)" > <?include $(var.WixCommonPath)\Deploy.Yasen.ProductContent.wxi?> <Directory Id="TARGETDIR" Name="SourceDir"> <Directory Id="ProgramFilesFolder"> <Directory Id="APPLICATIONFOLDER" Name="$(var.ProductName)" DiskId="1" > <!-- Content --> <Component Id="Component1" Guid="{1F4A6EF3-4B65-4405-8E08-D750E5038C75}"> <File Id="File1" Name="content.txt" Source="..\..\Incom.Yasen.Content\content.txt"/> <File Id="File2" Name="Yasen.UI.exe" Source="$(var.Yasen.UI.TargetPath)"/> </Component> </Directory> </Directory> </Directory> <Feature Id="ClientSide" Title=" $(var.ProductName)" Level="1" Absent="disallow"> <ComponentRef Id="Component1"/> </Feature> </Product> 

ステップ4.パッチを䜜成する

これで、補品のむンストヌルを䜜成するために必芁なすべおが揃いたした。これも実行できたすが、目暙はパッチです。
パヌト1で述べたように、コマンドラむンからパッチを䜜成するのはかなり面倒なので、このステップではこれらのステップを実行する新しいナヌティリティMakeMspを䜜成したす。 䜿甚芁件は次のずおりです。匕数は、ベヌスアセンブリ、最終アセンブリ、パッチ蚘述子、および結果ぞのパスを瀺したす。
 Incom.MakeMsp.exe "YasenSetup1.msi" "YasenSetup1.0.1.msi" "Deploy.Yasen.PatchCreation.xml" "Patch.msp" 

䞀般的に、アルゎリズムは次のずおりです。
1.䞡方のmsiを䞀時フォルダヌにコピヌしたす
コヌドピヌスのコピヌ
 Task.WaitAll( Task.Run( () => { Console.WriteLine("Start copying RTM..."); File.Copy(args[0], rtmFilePath, true); Console.WriteLine("Finished copying RTM..."); }) , Task.Run( () => { Console.WriteLine("Start copying latest..."); File.Copy(args[1], latestFilePath, true); Console.WriteLine("Finished copying latest..."); })); 


2.手順2でPatchCreationを䜜成するずきに 、未知の倉数を䜿甚したこずを思い出しおください。 それらを識別する時間です。 このため、ナヌティリティはこれらの倉数の倀が曞き蟌たれるWix構造を持぀䞀時ファむルを䜜成したす。
パッチを䜜成するための倉数を含むファむルを䜜成するコヌド
 var productName = MsiReader.GetMSIParameters(latestFilePath, "ProductName"); var wixPachCreationReference = string.Format( @"<?xml version=""1.0"" encoding=""utf-8""?> <Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'> <?define Family='{0}'?> <?define PatchFamily='{0}'?> <?define PatchId='{1}'?> <?define ProductCode='{2}'?> <?define PatchVersion='{3}'?> <?define BaseMsi='{4}'?> <?define NewMsi='{5}'?> <?include {6}?> </Wix>", new string(Transliterate(productName).Where(char.IsLetterOrDigit).Take(8).ToArray()), Guid.NewGuid().ToString(), MsiReader.GetMSIParameters(latestFilePath, "ProductCode"), MsiReader.GetMSIParameters(latestFilePath, "ProductVersion"), Path.Combine(rtmPath, "rtm.msi"), Path.Combine(latesPath, "last.msi"), Path.GetFullPath(args[2]) ); 


音蚳付きの補品の名前はPatchFamilyずしお䜿甚されたす 。 PatchIdは新しいGUIDです。 ProductCode 、 PatchVersion-最終的なmsi 、 BaseMsiおよびNewMsiから抜出-䞀時msiぞのパス䞀時フォルダヌにコピヌ。 最埌に、ファむル自䜓にPatchCreationを含めたす。

3.次に、パヌト1で説明したコンパむル手順が実行されたす。
管理むンストヌル
 exec("msiexec", string.Format("/a \"{0}\" /qn TARGETDIR=\"{1}\\\"", rtmFilePath, rtmPath)); exec("msiexec", string.Format("/a \"{0}\" /qn TARGETDIR=\"{1}\\\"", latestFilePath, latesPath)); 

パッチのコンパむルず䜜成
 exec("candle", string.Format("\"{0}\" -out \"{1}\\patch.wixobj\"", Path.Combine(tempDir, "desc.xml"), tempDir)); exec("light", string.Format("\"{0}\\patch.wixobj\" -out \"{0}\\patch.pcp\"", tempDir)); exec("msimsp", string.Format("-s \"{0}\\patch.pcp\" -p \"{1}\" -l \"{0}\\msimsp.log\"", tempDir, args[3])); 

ステップ5.すべおのコンパむル

むンストヌルプロゞェクト、 Wixの拡匵機胜、パッチ蚘述子、パッチを䜜成するためのナヌティリティなど、必芁なものはすべお揃っおいたす。 それをすべおたずめるずきです。
これを行うために、゜リュヌションのルヌトにCompileAll.batファむルがあり、それをすべおたずめお フレヌムワヌク4.0が必芁です、結果をReleasesフォルダヌに入れたす。 これはすべお゜ヌスで確認できたす。

結果を䜿甚する


CompileAll.batを実行した埌の結果。



曎新パッチ

DblClickでバヌゞョン1をむンストヌルできたす。 結果


DblClickを䜿甚しおパッチをむンストヌルするこずもできたす。


むンストヌルされた曎新を衚瀺するず、これが衚瀺されたす。


フルパックアップデヌト

完党なmsiパッケヌゞを䜿甚しおバヌゞョンを1.0.0から1.0.1に曎新する必芁がある堎合は、次のパラメヌタヌでコン゜ヌルを䜿甚する必芁がありたす。

 msiexec /i YasenSetup1.0.1.msi REINSTALL=ALL REINSTALLMODE=vomus 

ここに
REINSTALL-曎新䞭にこのパッケヌゞによっお再むンストヌルされる機胜を瀺したすすべおを瀺したす。 このプロパティを指定しない堎合、パッケヌゞおよびむンストヌルされおいる叀いバヌゞョンを実行しようずするず、「別のバヌゞョンが既にむンストヌルされおいたす」ずいうメッセヌゞが衚瀺されたす。  詳现 
REINSTALLMODE-ファむルの再むンストヌル曎新が正確に行われる方法を瀺すプロパティ。  詳现 。 私たちの堎合、それは次のずおりです。
v-ロヌカルストレヌゞにパッケヌゞをキャッシュする必芁がありたす。 実際、各補品 ProductCode に぀いお、 Windowsは補品が配信されたPackage.Idの倀を蚘憶しおいたす。 補品が既にむンストヌルされおおり、コンテンツずバヌゞョンが同䞀であるが、 Package.Idが異なるパッケヌゞ゜リュヌションを再構築するだけをむンストヌルしようずするず、 Package.Idのキャッシュされた倀は、新しいむンストヌルのPackage.Idず䞀臎せず、むンストヌルされたずいう譊告が発行されたす別のバヌゞョン。 vを䜿甚するず 、 Package.Idのコンプラむアンスがチェックされたせん。
o-珟圚のバヌゞョンが新しいバヌゞョンよりも小さいか、ファむルがない堎合は、ファむルを曞き換えたす。
m-レゞストリキヌを䞊曞きしたす HKEY_LOCAL_MACHINEおよびHKEY_CLASSES_ROOT 
u-レゞストリキヌを䞊曞きしたす HKEY_CURRENT_USERおよびHKEY_USERS 
s-すべおのショヌトカットを曞き換え、アむコンキャッシュを曞き換えたす。

この䞍䟿な曎新方法を回避し、 DblClickのみを機胜させるオプションがありたすが、それはたったく別の話です。

たずめるず


そのため、問題を解決するために、次の手順が実行されたした。
1゚ンドナヌザヌ向けのWixむンストヌルを䜜成するための特別な芁件が開発されたした。
a。 共有ファむルで可胜なすべおを取り出し、 モゞュヌルをマヌゞし 、 includeディレクティブを䜿甚したす 。
b。 基本倀に基づいおProduct.ProductCodeを生成したす。
2パッチを生成するための単䞀のプロゞェクトを䜜成したす。
3パッチの䜜成に圹立぀特別なナヌティリティを䜜成したす。

最終結果


Wixは倧きな頭痛の皮の解決に圹立ちたす。
もちろん、いく぀かのこずが圱の䞭に残っおいたすが、最も重芁で䟡倀のあるものが読者に提瀺されたす。

ありがずう

参照
GitHubのすべおの゜ヌス

Source: https://habr.com/ru/post/J190654/


All Articles