簡體   English   中英

Wix Installer:在命令行執行MSIEXEC管理員安裝時設置組件條件屬性

[英]Wix Installer : Setting component condition property when doing a MSIEXEC admin install at command line

我們的產品有三種類型/口味,但是只有一種用WiX編寫的MSI。 在構建安裝程序時,我們通過定義的常量傳遞風味:

Call MSBUILD.bat ..\MSIs\CoreProduct\OurProduct.sln /p:DefineConstants="FLAVOUR=%_Flavour%"

並在Visual Studio中的“構建”->“將預處理器變量定義為FLAVOUR = 50”下設置該常數。 構建過程會傳遞50、200或LITE值作為風味。

在WiX代碼中,我們在組件上有很多條件,可以根據不同的情況告訴它要安裝哪個文件。 例如

      <Component Id="cmp7F45920B1AA100729BAE37FC846B3FC5" Guid="*">
    <File Id="fil238A776D9294E14671E012472F9F7196"
          KeyPath="yes"
          Source="$(var.MenusPath)\ClientListView 200.r5m"  
    <Condition>$(var.FLAVOUR)=200</Condition>
  </Component>

      <Component Id="cmp8BFF42B232724DC4BA5B8F87994DEF21" Guid="*">
    <File Id="fil808D6428D67248DDB8CA65DBC5978283" 
          KeyPath="yes" 
          Source="$(var.MenusPath)\ClientListView Lite.r5m"
    <Condition>$(var.FLAVOUR)=LITE</Condition>
  </Component>

因此,如果FLAVOR是LITE,則上面的示例將安裝一個名為“ ClientListView Lite.r5m”的文件;如果FLAVOR是200,則將安裝一個名為“ ClientListView 200.r5m”的文件。

這一切都按預期進行,並且已經完成了多年!

但是現在,我們有了產品的Web版本,我們需要一個zip文件來包含每種風味將安裝的文件夾結構和文件。 我發現您可以使用MSIEXEC和/ a參數在命令行上運行msi,然后它將重定向所有本應安裝到文件夾中的內容,並認為這正是我想要的...但是a,它無法正常工作預期的。

似乎正在運行MSI,然后將文件提取到目標文件夾中,但是它忽略了這種風格,因此最終將“ ClientListView Lite.r5m”和“ ClientListView 200.r5m”文件提取到文件夾; 這顯然不是我想要的。

閱讀有關MSIEXEC的文檔后,似乎可以傳遞Public屬性的值,例如msiexec.exe / a“ C:\\ Example.msi” MY_PROP =“ myValue”-因此,我認為這可能對我有所幫助; 因此,在我的WiX代碼中,添加了以下行:

    <Property Id='PRODTYPE' Value="$(var.FLAVOUR)"/>

然后將我的組件條件更改為:

  <Component Id="cmp7F45920B1AA100729BAE37FC846B3FC5" Guid="*">
    <File Id="fil238A776D9294E14671E012472F9F7196"
          KeyPath="yes"
          Source="$(var.MenusPath)\ClientListView 200.r5m"  
    <Condition><![CDATA[PRODTYPE=200]]></Condition>
  </Component>

  <Component Id="cmp8BFF42B232724DC4BA5B8F87994DEF21" Guid="*">
    <File Id="fil808D6428D67248DDB8CA65DBC5978283" 
          KeyPath="yes" 
          Source="$(var.MenusPath)\ClientListView Lite.r5m"
    <Condition><![CDATA[PRODTYPE=LITE]]></Condition>
  </Component>

但是盡管編譯正常,但可以通過以下方式運行它:

msiexec /a OurProduct.msi /qb PRODTYPE=200 TARGETDIR="C:\InstalledFiles200"

仍然提取200和LITE口味的兩個文件,而我只想提取200個。

因此,我是在嘗試做一些不可能的事情...還​​是我在做錯什么-感激不盡的幫助,因為可以在批處理文件中模仿該過程來創建我的zip; 將是可怕的!

干杯,

克里斯。

通常,msiexec命令行中的/ a開關不是安裝。 實際上,這只是將文件解壓縮到某個位置。 如果要實際安裝,則必須使用/ i或雙擊MSI文件。 這將為您提供正確的完整安裝,並在Programs&Features等條目中有一個條目。

通常,通過將安裝分為功能來處理安裝內容的選擇,每個功能都包含一組包含所需功能的組件。 在WiX UI中,您可以找到一個對話框來選擇功能,而維護模式將使您返回並對其進行更改。 在命令行安裝中,您只需說/ i [msi文件] ADDLOCAL = Feature1,Feature2,依此類推。 如果您真的想使用“風味”,則在內部將其轉換為ADDLOCAL列表。

您的預處理器使用

當我意識到您只想要一個MSI(至少一次-看起來)時,我在建議使用預處理器結構?if?等)時中途回答,所以我跳過了它。 我通常使用這種構造來編譯來自同一WiX源的MSI文件。 我已經將我在下面寫的內容轉儲了一些,沒有進行過多的評論。 我稍后會檢查。

在您的情況下,我可能會遺漏某些東西,但是我看不出怎么?if? 該語句可以在安裝時工作- 這是一個編譯時的構造 在編譯和鏈接之前,它會對WiX源文件進行預處理。 因此,聽起來您實際上已經編譯了MSI文件的三個不同版本,然后在每個版本上運行admin install? 如果是這種情況,那么使用管理映像就無關緊要了,因為您的整個MSI並不包含任何內容,而是您包含在?if?的組件?if? -無需傳遞任何版本的屬性規范。


設置風味

當我需要創建不同的安裝風格產品版本時,我使用的常規技術方法如下:

  1. 預處理器構造用於在編譯時編譯 MSI的不同版本或版本(也包括不同的語言版本)。 ?if?就是這樣一種構造?if? 您提到的聲明。 如上面直接提供的鏈接所示,還有其他幾種。 與您相關的是條件語句ififdefifndefelseelseifendif )和可能的include語句。

    • 因此,總體信息是, 預處理器構造使您可以從單個WiX XML源構建幾種不同類型的MSI文件

    • 在您的情況下,這將產生一個WiX XML源三個MSI文件 -每個文件用於不同版本的應用程序。 都相似,但是只需要它們所需的組件。

    • 通過運行安裝/i或通過管理映像(文件提取物) /a而是三個不同的人要看你如何編譯-會產生只有你添加到該設置風味成分,但你沒有一個單一的MSI像你說的。

    • 我更喜歡使用?include? 包含WiX片段文件的語句,而不只是直接使用?if?條件組件?if? 正如你提到的。 在“ 預處理器構造 ”部分的底部有一個差異示例。

  2. MSI功能 (如PhilDW回答的那樣) 您還可以依靠MSI功能來提供不同口味的單個設置。 功能用於將MSI分為各種用戶可選擇的安裝項目(其中一些可以強制執行)。

    • 功能允許單個MSI以不同的口味安裝 -同時包含每種口味所需的所有組件。 調理組件可以達到類似的效果。
    • 條件組件類似於功能操縱,但在更原始和更基礎的級別上工作。 這些不是用戶可選擇的安裝單元,而是要安裝的產品的基本和基本的零組件,對於用戶而言是隱藏的,而功能是用戶可選擇的,並且通常對用戶可見。
    • 用戶可以調整 要安裝的功能,也可以通過自定義操作以編程方式進行操作(例如,覆蓋用戶規范並自動強制實施技術設計)。

      • 用戶功能控制

        • 用戶可以通過大多數設置(並非全部)中找到的安裝程序的FeatureTree對話框來控制功能以進行交互式安裝。 通常,這涉及選擇進行“自定義”安裝。

        • 您還可以使用ADDLOCAL屬性REMOVE屬性 (以及可能的其他相似屬性-通過鏈接了解詳細信息),通過命令行指定要在安裝程序中安裝哪些功能。

        • 有時,您可以在安裝過程中設置一個自定義屬性,該屬性將根據指定的“版本”觸發要安裝的一組標准功能,這將使我們進入下一步。

      • 程序特征控制

        • 將鏈接添加到有關程序化功能控件的答案: 如何根據在自定義操作中設置的屬性安裝功能?

        • 如前所述,您可以在安裝程序運行時通過其內部的ADDLOCAL屬性REMOVE屬性來控制通過命令行安裝哪些功能。 為此,您可以使用自定義操作

        • 還有一個INSTALLLEVEL屬性 ,與功能的安裝狀態有關。 對於每個功能,都有一個安裝級別,並且可能會受“ 條件”表中設置的條件影響。

          • 因此,條件表可用於基於條件表達式來修改功能表中任何條目的選擇狀態。

          • 換句話說,您可以使用此功能根據條件將功能設置為默認安裝或不安裝。

        • 除了INSTALLLEVEL概念外,您還可以使用自定義操作來控制特征選擇狀態。

          • 今天,這比功能狀況更可靠,因為許多應用程序打包程序通常會最大化INSTALLLEVEL屬性來強制安裝所有功能。 這是錯誤的,因為如果某些功能與您所運行的操作系統不兼容,則可能不需要安裝這些功能 我已經嘗試將其傳達給許多充耳不聞的人。
        • 使用這些程序結構,您的設置可以例如根據用戶輸入的序列號更改要安裝的功能的功能選擇狀態。

        • 您的設置還可以根據正在運行的操作系統確定不應安裝某些功能(例如,不要安裝Tablet OS功能)。

        • 以編程方式更改功能選擇可能有許多技術和實踐原因。

    • 重要的是要注意,總體結果是可以通過命令行或用戶設置功能選擇,然后出於技術原因,您的設置會進行一些“幕后”修改。

    • 需要指出的是:以編程方式進行安裝操作的功能通常從視圖中隱藏(但仍然可以通過命令行覆蓋-這可能是一個問題)。

    • 有關安裝的功能,組件和自定義設置的更多信息,請點擊此處: 如何更好地利用MSI文件

  3. Setup.exe啟動器 :一種以不同方式進行復雜部署的“現代”方法可以是使用WiX的Burn功能來編譯安裝在不同“集合”中的較小MSI安裝程序,以產生不同的安裝狀態。

    • 我發現這對於一般用途來說太復雜了,但是肯定是可能的。 我認為有些人發現它更容易,因為功能操縱較少。 也許我只是缺乏經驗。
    • 好處是較小的MSI文件可以更快地安裝,您可以更新單個MSI文件並創建新的setup.exe包裝器,然后對整個解決方案進行總質量檢查,而無需重建所有設置。
    • 在我的世界中,無論如何,一個更新的MSI仍然需要完整的質量檢查,因此我並不總是自己購買這些“簡單性論證”。 每個發布周期都有風險,因此會增加總風險 但是,能夠重建一個很小的設置並保持大型的穩定狀態可能很棒。

實際使用

我更喜歡盡量減少設置風格 ,但是大多數時候我都會使用預處理器構造為不同的語言版本 (英語,德語,俄語)和不同的產品版本 (企業版,專業版,標准版)創建不同的設置。 。 我通常將所有相關的共享設置為升級代碼,並且不能並行安裝。

我覺得單個MSI可以獲得更多的質量檢查資源,因此將得到更好的測試。 但是,如果設置非常大,則這種單一的MSI方法通常會崩潰-在這種情況下,我希望將它們拆分。 我還喜歡出於業務和現實中的實際原因,為每種語言進行單獨的設置。 實際和法律要求(許可)還可能必須編譯同一MSI安裝程序的特殊版本。 我還被要求為OEM供應商構建新的MSI版本。

現在得出一個令人驚訝的結論 (您從未要求過:-)):話雖如此,在理想的世界中,我喜歡安裝所有功能,而無需在設置中進行任何技術麻煩,並使用序列號確定應用程序的功能和模塊應在應用程序中激活。 我還喜歡將串行密鑰驗證放入應用程序中,而不是放在安裝程序中。 原因是什么? 我希望安裝程序盡可能原始,以確保正確安裝應用程序而不會導致較高的部署錯誤百分比。 因此,我尋求在部署中消除復雜性,以確保減少部署支持問題。 可靠的部署對於產品的成功至關重要 安裝后,您的應用程序可以在更加可調試和可預測的上下文中啟動(無條件,模擬或排序問題),並以交互方式向用戶有意義地報告任何錯誤-他們可以致電支持部門,他們更有希望成功解決任何問題如果安裝程序只是用神秘的非交互式錯誤消息(在系統的事件日志中)轟炸了,情況將不會如此。

一旦有了一個好的,簡單的部署解決方案,您作為發行經理和設置開發人員的工作應擴展到照顧應用程序的啟動順序,文件配置和整體配置,以及我認為您可能希望添加到應用程序中的支持和調試功能。應用程序(應用程序的自檢以及日志記錄和自動收集信息以發送給支持人員)。 嘗試擴大您對應用程序本身的責任和影響,以使部署“盡可能原始”。 從長遠來看,任何可以在應用程序中而不是安裝程序中進行編碼的東西都將更加可靠(並且更容易調試)。

回到現實中 :對於真正的部署,您將通過緩慢的網絡共享獲得一堆帶有不規則版本控制方案的文件,以及來自離岸並按小時付費的開發人員的一堆不連貫的指令(您可以確定他會感到痛苦)也是:-))。 他們將對您的設置有很多瘋狂的要求,以制作魔術來掩蓋其不理想的設計(這是他們付錢做的全部)。 這不是誇大其詞,它是現實-真難( 好吧,這是在胡說八道 )。 我們必須努力改善應用程序的整體設計,以減少部署中易於出錯的地方。 魔術確實可以在安裝程序中完成,但是由於不可避免且難以控制的部署復雜性 (最重要的是: 1)錯誤是累積性的 ,因此它將觸發更高的部署錯誤百分比-每個版本都會增加風險和機會,破壞安裝的可服務性(有時您必須撤回所有內容並重新開始-付出高昂的代價), 2)目標系統處於極其多樣且不可預測的狀態(任何狀態,任何語言,任何OS版本,任何硬件,任何惡意軟件等)。 , 3)當您無法以交互方式訪問問題系統時,調試將非常困難-有關更多詳細信息,請參見鏈接答案的底部。 我將添加第二4th issue ,而不是第二個問題: 您能否保證在充滿惡意軟件的計算機上進行部署? 這樣的系統無法支持和調試-只需選擇您發現的無法解決的關鍵問題即可。 如果您的軟件包在此類惡意軟件系統上失敗,則不可避免的是自然錯誤百分比

總的來說很明顯: 我們無法解決這些未知數-垃圾進,垃圾出(用道歉的方式道歉)-每次部署時都會出現錯誤百分比-即使是完美的軟件包也是如此 確保抓住所有可用且始終有價值的QA專家,並教給他們有關設置測試的信息(測試所有安裝模式,測試卸載和與其他應用程序的交互,測試實際的升級方案,測試特定的高級設置功能(例如許可證檢查)等) ...)。 獲得所有可獲得的幫助,並重視他們的貢獻。 如果沒有別的,作為同謀:-)。 嚴重的是:在我作為發布經理和安裝開發人員的最大的疏忽時,在我的榜單上,未能有效利用可用的QA資源並幫助他們進行部署測試培訓是我的首要任務。 可以肯定的是,您將立即欠您的質量檢查人員一瓶Horílka-或綠茶或Rooibos茶-取決於您在世界上的位置:-)。


預處理器構造

我可能會使用預處理器構造 ?if? ?include? 根據定義的版本有選擇地包括WiX XML源代碼/標記的不同部分?define? 樣本頂部的語句:

<?define EditionType = “LITE” ?>

<!-- You can put your edition-specific components in an include file  -->
  <?if $(var.EditionType) = "200" ?> 
    <?include "200Features.wxi" ?>
  <?endif ?>
  <?if $(var.EditionType) = "LITE" ?>
    <?include "LiteFeatures.wxi" ?>
  <?endif ?>

除了使用包含文件,您還可以在主要源代碼中內聯執行此操作(這可能是您已經完成的操作):

 <?if $(var.EditionType) = "200" ?> 
    <Component>
       <File Source="$(var.MenusPath)\ClientListView 200.r5m" /> 
    </Component>
<?endif?>
<?if $(var.EditionType) = "LITE" ?>
    <Component>
       <File Source="$(var.MenusPath)\ClientListView Lite.r5m" />
    </Component>    
<?endif?>

在上述選項中,我希望將特定於版本的組件保留在單獨的包含文件中(第一個選項)-這樣,WiX源中的“行噪”就更少了(預處理器結構的重復次數減少了)。

包含文件基本上只是WiX XML文件,就像在編譯時將C ++頭文件包含到父WiX XML文件中一樣。 就像Phil所說的那樣,我會在不同版本中使用不同的功能名稱,因此您可以在200Features.wxi包含文件中定義一個功能200Features ,但是盡管強烈建議您使用功能,但您無需使用這些功能。

還應注意片段元素的WiX概念。 本質上是一種交叉引用WiX源文件中的內容的方法。 這里有個例子

我應該提到,MSI中合並模塊的原始概念提供了一種在不同設置之間共享組件的不同方法,但是我更喜歡include file方法。 合並模塊感覺就像是COM對象(二進制的blob作為一個版本控制的整體包含在內),而包含文件似乎更加動態,因為您無需為任何合並模塊進行重建和版本控制就可以為每個構建鏈接到最新的文件。 無疑,某些人會發現這是非常錯誤的。

感謝您提供的信息,但是我想您錯過了我試圖實現的目標; 我不想通過/ i運行安裝程序,因為正如您所說的那樣,這實際上將安裝文件並更改注冊表等。我想做的是兩次運行安裝程序-一次運行口味200,然后再次運行口味Lite; 因此,如果使用/ i運行,我最終將得到兩個包含“將要安裝”文件的文件夾。 顯然,我無法使用/ i運行它兩次,因為第二次運行它會卸載第一個。

無論如何,我發現在管理員“安裝”過程中會忽略組件中的條件,而? 語句不會被忽略-不確定為什么,但是我現在刪除了所有條件語句,並用IF語句替換了-現在我可以做我想做的事情-用/ a運行兩次,每個文件夾將包含獨特風味的文件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM