Visual Studio 2017&C#打包應用程式詳細教程,重寫安裝類獲取安裝路徑,附加各種奇葩問題描述

Visual Studio 2017&C#打包應用程式詳細教程,重寫安裝類獲取安裝路徑,附加各種奇葩問題描述
  • 前言

C#寫好一個應用程式,總想分享給自己的朋友或者上架,然而被困在打包之外,這次為大家帶來近期我的經驗,經過幾天的摸索,發現網上的教程並不全面,會給初學者帶來很多疑問,這裡將做些問題描述與解答。
/**
開發工具:Visual Studio 2017
系統版本:win10 x64
要求:已經有一個已完成的專案
*/

  1. 獲取打包工具,使用微軟自帶工具,獲取步驟如下,若已安裝請忽略此步。

開啟工具->擴充套件和更新->搜尋(2017 installer)->點選安裝:
擴充套件和更新” title=””> 這裡寫圖片描述
這裡安裝擴充套件的具體步驟就不再贅述。
2. 安裝完擴充套件以後,新建一個Setup project專案。

這裡寫圖片描述介面如下
“應用程式資料夾”即”Application Folder”表示要安裝的應用程式需要新增的檔案;
“使用者的‘程式’選單”即”User’s Programs
Menu”表示:應用程式安裝完,使用者的“開始選單”中的顯示的內容,一般在這個資料夾中,需要再建立一個檔案用來存放:應用程式.exe和解除安裝程式.exe;
“使用者桌面”即”User’s Desktop”表示:這個應用程式安裝完,使用者的桌面上的建立的.exe快捷方式。
3. 解決方案->新增->新建專案->類庫,命名為ClassLibrary,在專案ClassLibrary下面,刪除Class1.cs,新增->新建專案->安裝程式類(名稱為InstallerDemo.cs),開啟Installer,這個class Installer繼承自System.Configuration.Install.Installer,裡面就一個建構函式。現在安裝程式不能完成的功能,都可以在這個類寫程式碼來自己實現。
4. 重寫安裝函式BeforeInstall,AfterInstall,AfterRollback,AfterUninstall,BeforeRollback,BeforeUninstall等複製以下程式碼實現自定義操作:
ps:這裡的OnAfterInstall操作是寫入登錄檔,自啟動

protected override void OnAfterInstall(IDictionary savedState)
{
LogWrite("OnAfterInstall!");
string path = this.Context.Parameters["targetdir"];//獲取使用者設定的安裝目標路徑, 注意,需要在Setup專案裡面自定義操作的屬性欄裡面的CustomActionData新增上/targetdir="[TARGETDIR]\"
LogWrite(path);                                                //開機啟動
RegistryKey hklm = Registry.LocalMachine;
RegistryKey run = hklm.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run",true);
try
{//64位系統在計算機\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run
LogWrite("設定登錄檔!");
LogWrite(path.Substring(0, path.Length - 1)   @"BingPic\BingPic.exe");
run.CreateSubKey("Bing",true);
run.SetValue("Bing", path.Substring(0,path.Length-1)   @"BingPic\BingPic.exe");
hklm.Close();
LogWrite("設定結束!");
}
catch (Exception my)
{
my.ToString();
LogWrite(my.ToString());
}
base.OnAfterInstall(savedState);
}
public override void Install(IDictionary stateSaver)
{
LogWrite("Install!");
base.Install(stateSaver);
}
protected override void OnBeforeInstall(IDictionary savedState)
{
LogWrite("OnBeforeInstall!");
base.OnBeforeInstall(savedState);
}
public override void Uninstall(IDictionary savedState)
{
LogWrite("Uninstall!");
base.Uninstall(savedState);
}
public override void Rollback(IDictionary savedState)
{
LogWrite("Rollback");
base.Rollback(savedState);
}
public void LogWrite(string str)
{
string LogPath = @"c:\log\";
using (System.IO.StreamWriter sw = new System.IO.StreamWriter(LogPath   @"SetUpLog.txt", true))
{
sw.WriteLine(DateTime.Now.ToString("[yyyy-MM-dd HH:mm:ss] ")   str   "\n");
}
}

實現以上還不能應用到你的程式中,接下來新增主程式入口。
5. 新增主程式入口:“application folder 應用程式資料夾”–右側空白處右鍵–“新增”–“專案輸出”
**這裡寫圖片描述
專案Setup1 ->新增->專案輸出->選擇ClassLibrary後確定,你會發現,在專案Setup1 下面多了一項“主輸出來自ClassLibrary(活動)”的字樣。這裡寫圖片描述
6. 新增自定義操作: 可以看到四個子項:安裝,提交,回滾,解除安裝。在安裝上面點選右鍵->新增自定義操作->選擇“主輸出來自ClassLibrary(活動)”。這樣,重新生成後,安裝之後就會執行 OnAfterInstall程式碼了。
這裡寫圖片描述這裡寫圖片描述
ps:獲取使用者設定的安裝目標路徑, 注意,需要在Setup專案裡面自定義操作->install->輸出的屬性欄裡面的CustomActionData新增上/targetdir=”[TARGETDIR]\”這裡寫圖片描述這樣程式碼裡就可以獲取到安裝路徑了
7. 新增解除安裝程式:c:\windows\system32\msiexec.exe
這裡寫圖片描述
獲取資源管理器”:點選專案setup1,屬性>-“ProductCode” ,將它的值複製,後面需要使用,很重要。
這裡寫圖片描述
8. 新增你的已存在專案檔案:debug目錄下的檔案新增到應用程式資料夾裡。這裡寫圖片描述
9. 建立應用程式快捷方式,解除安裝快捷方式.並重新命名為你希望的,剪下並黏貼到桌面資料夾和使用者程式資料夾這裡寫圖片描述這裡寫圖片描述
這裡寫圖片描述這裡寫圖片描述
並在解除安裝快捷方式的屬性中新增之前複製的欄位
最後生成應用程式即可。這裡寫圖片描述
至此你的第一個應用程式就打包好了。這裡寫圖片描述這裡寫圖片描述現在去測試吧!

這個例子中在寫入登錄檔時遇到了不少難題,其中一個很迷惑人的就是:
System.UnauthorizedAccessException: 無法寫入到登錄檔項。
在 System.ThrowHelper.ThrowUnauthorizedAccessException(ExceptionResource resource)
在 Microsoft.Win32.RegistryKey.EnsureWriteable()
在 Microsoft.Win32.RegistryKey.SetValue(String name, Object value, RegistryValueKind valueKind)
在 Microsoft.Win32.RegistryKey.SetValue(String name, Object value)
在 MyInstall.InstallerBing.OnAfterInstall(IDictionary savedState)

後來找資料說是未將RegistryKey run = hklm.OpenSubKey(@”SOFTWARE\Microsoft\Windows\CurrentVersion\Run”,true);設為true,之後解決。

操作登錄檔時還有一個問題就是寫入成功,找不到的問題,
在32位機上自啟動路徑位:計算機\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
64位:計算機\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run

最後設定的CustomActionData新增上/targetdir=”[TARGETDIR]\”,一定要寫對 /targetdir=”[TARGETDIR]\”

歡迎大家指出問題。