分類
    • 主機維護
    • 程式語言
    最新文章

    C# .Net 控制 Windows 的 Wifi 連線

    2024 年 8 月 28 日

    C# .Net 6 匯入至 Windows 憑證

    2024 年 8 月 28 日

    C# .Net 6 刪除 Windows 下的使用者

    2024 年 7 月 31 日

    C# .Net 6 取得 Windows 列印的紀錄 Log

    2024 年 7 月 31 日
    Facebook Instagram
    Facebook Instagram Telegram
    2kH – Technology Log
    • 首頁
    2kH – Technology Log
    Home»程式語言»C# .Net 6 程式封裝 MSI 安裝檔
    程式語言 2023 年 2 月 21 日

    C# .Net 6 程式封裝 MSI 安裝檔

    使用 .net 6 寫的 Worker Service 編譯為 Windows 服務後,需要提供給客戶安裝使用
    原本是使用 NSIS 打包成 exe 的安裝檔,但是客戶希望使用 MSI 大量派送安裝
    故研究了一下使用 WiX Toolset 似乎是較為理想的方式,可以透過 XML 編輯

    WiX Toolset: https://wixtoolset.org

    目前 Wix 的版本 4 好像還沒有正式版,所以是安裝 3.11 版本

    透過官方網站提供的下載點(Github Release)可以下載到最新版本的安裝檔
    除了 WiX 本身的安裝檔之外官方網站也有提供 WiX v3 – Visual Studio 2022 Extension
    方便我們在 Visual Studio 2022 的環境下可以建立 WiX 專案

    使用 Setup Project for WiX v3 的專案建立

    建立後可以發現目錄底下有 Product.wxs 檔案,這是 MSI 安裝程式主要的 XML 結構如下

    <?xml version="1.0" encoding="UTF-8"?>
    <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    	<Product Id="*" Name="SetupProject1" Language="1033" Version="1.0.0.0" Manufacturer="" UpgradeCode="7ab0bd7e-538d-407a-bca5-a497bba02c97">
    		<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
    
    		<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
    		<MediaTemplate />
    
    		<Feature Id="ProductFeature" Title="SetupProject1" Level="1">
    			<ComponentGroupRef Id="ProductComponents" />
    		</Feature>
    	</Product>
    
    	<Fragment>
    		<Directory Id="TARGETDIR" Name="SourceDir">
    			<Directory Id="ProgramFilesFolder">
    				<Directory Id="INSTALLFOLDER" Name="SetupProject1" />
    			</Directory>
    		</Directory>
    	</Fragment>
    
    	<Fragment>
    		<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
    			<!-- TODO: Remove the comments around this Component element and the ComponentRef below in order to add resources to this installer. -->
    			<!-- <Component Id="ProductComponent"> -->
    				<!-- TODO: Insert files, registry keys, and other resources here. -->
    			<!-- </Component> -->
    		</ComponentGroup>
    	</Fragment>
    </Wix>
    

    註解的地方是要放置檔案的位子

    幾個比較重要的欄位需要注意

    Product – Id: 這個是對應安裝完成後的 Product Code 輸入 * 的話每次安裝完成後都會隨機產生 Guid

    Product – Version: 這個是 MSI 安裝完成後的版本,之後如果有做更新服務,會參考此版本號

    Product – UpgradeCode: 這個是更新 MSI 用的,如果是相同的 Code 會做更新否則會視為不同軟體

    輸入重要欄位的資訊後,接著可以使用 File 建立要放入的檔案

    <?xml version="1.0" encoding="UTF-8"?>
    <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    	<Product Id="*" Name="Main Service" Language="1033" Version="0.1.2" Manufacturer="Technology lnc" UpgradeCode="6fa4caeb-d239-49c2-bdd8-ae8c0e84d9dd">
    		<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
    
    		<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
    		<MediaTemplate EmbedCab="yes" />
    
    		<Feature Id="ProductFeature" Title="GDMS" Level="1">
    			<ComponentGroupRef Id="ProductComponents" />
    		</Feature>
    
    	</Product>
    
    	<Fragment>
    		<Directory Id="TARGETDIR" Name="SourceDir">
    			<Directory Id="ProgramFilesFolder">
    				<Directory Id="INSTALLFOLDER" Name="Main Service" />
    			</Directory>
    		</Directory>
    	</Fragment>
    
    	<Fragment Id="FileFragment">
    		<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
    			<Component Guid="*">
    						<File Source="C:\temp\main.exe" />
    			</Component>
    
    			<Component Guid="*">
    				<File Source="C:\temp\service.dll" />
    			</Component>
    
    		</ComponentGroup>
    	</Fragment>
    </Wix>
    

    這樣加入了兩個檔案分別為 main.exe 與 service.dll

    INSTALLFOLDER 表示安裝的路徑

    接著因為是要安裝成為服務,所以除了安裝檔案之外還要加入安裝服務的控制項

    <?xml version="1.0" encoding="UTF-8"?>
    <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    	<Product Id="*" Name="Main Service" Language="1033" Version="0.1.2" Manufacturer="Technology lnc" UpgradeCode="6fa4caeb-d239-49c2-bdd8-ae8c0e84d9dd">
    		<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
    
    		<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
    		<MediaTemplate EmbedCab="yes" />
    
    		<Feature Id="ProductFeature" Title="GDMS" Level="1">
    			<ComponentGroupRef Id="ProductComponents" />
    		</Feature>
    
    	</Product>
    
    	<Fragment>
    		<Directory Id="TARGETDIR" Name="SourceDir">
    			<Directory Id="ProgramFilesFolder">
    				<Directory Id="INSTALLFOLDER" Name="Main Service" />
    			</Directory>
    		</Directory>
    	</Fragment>
    
    	<Fragment Id="FileFragment">
    		<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
    			<Component Guid="*">
    				<ServiceInstall Id="MainServiceInstall" Name="MainService"
                      DisplayName="Main Service"
                      Description="Main Service"
                      ErrorControl="normal"
                      Type="ownProcess"
                      Vital="yes"
                      Start="auto"
                      Account="LOCALSYSTEM"
                      Interactive="no" />
    				<ServiceControl Id="MainService" Name="MainService" Start="install" Stop="both" Remove="uninstall" Wait="yes"/>
    				<File Source="C:\temp\main.exe" />
    			</Component>
    
    			<Component Guid="*">
    				<File Source="C:\temp\service.dll" />
    			</Component>
    
    		</ComponentGroup>
    	</Fragment>
    </Wix>
    

    有些 Id 需要有些不用,我 Id 都亂填的 …

    使用 ServiceInstall 加入這個 Windows 服務,並用 ServiceControl 控制服務

    這樣簡單 Windows 服務封裝的 MSI 檔就完成了

    針對專案建置後,即可在目錄底下產生 MSI 的安裝程式

    另外目錄底下會有一個 wixpdb 的檔案,也可以把此檔案一同壓縮進 MSI 程式

    在專案的屬性頁面 Build 分頁中的 Suppress output of the wixpdb files 選項勾選後

    在編譯 wixpdb 檔案就一起被包進 MSI 安裝程式了~

    Ubuntu 下封裝 MSI

    另外因為其他需求需要再 Ubuntu 環境下封裝 MSI

    可以使用 wixl

    sudo apt install wixl

    就可以把 wxs 檔案放置指定目錄然後使用 wixl 指令進行封裝

    wixl -v product.wxs -o /var/output/product.msi

    詳細的命令參數可以參考: https://manpages.ubuntu.com/manpages/xenial/man1/wixl.1.html

    wixl 和 WiX Toolset 雖然都是使用同樣的 XML 進行封裝
    但是因為是不同程式與版本,有些 XML 的物件支援度不一樣,這裡產生了很多問題 …
    有些 Tag 在 wixl 需要 Id 而 WiX Toolset 不需要,甚至有些 Tag wixl 直接沒有支援
    挺多問題的,官方文件也沒有寫得十分清楚,只能慢慢測試了~

    .Net C# MSI Ubuntu Windows WiX Toolset

    Leave A Reply Cancel Reply

    關於作者
    關於作者
    我是軟體工程師 2kH
    這裡是用來記錄工作上遇到的事物
    如果有問題想詢問,或者有合作可能
    歡迎來信:2kh@bshade.net
    本部落格文章版權所有
    未經授權,不得進行任何營利行為
    • Home
    © 2025 idawn. All Rights Reserved by 2kH

    Type above and press Enter to search. Press Esc to cancel.