文章目錄
- VS2022 - C#程序簡單打包操作
- 概述
- 筆記
- 實驗過程
- 新建工程
- 讓依賴的運行時程序安裝包在安裝時運行(如果發現運行時不能每次都安裝程序,就不要做這步)
- 關于”運行時安裝程序無法每次都安裝成功“的應對
- 知識點
- 嘗試打包
- 舊工程bug修復
- 從需求屬性中,可以原作者勾選的dotnet組件去掉
- 備注
- 打包工程要注意編譯信息和運行時的報錯信息
- END
VS2022 - C#程序簡單打包操作
概述
以前用VS2019對C++程序打包做了一個筆記(vs2019 - 打包(開發機win10x64 - 目標機win7x64 - debug版程序))
有個打包新手同學(剛接觸C#打包,才接觸了10天),要對C#寫的測試程序進行打包,自己搞不定。私信讓我幫他搞一下。
看他私信明確要求是有償服務,就幫他搞一下。如果沒看到有償字樣的胡言亂語,俺應該直接將私信刪了,沒義務啊。
打包的事情全部依賴于VSIDE, 作為用戶,我們如果要簡單打包,需要的操作特別少,只需要幾個固定的步驟就可以完成一個簡單的打包。
這個筆記作為解決完問題的一個記錄,也作為C#打包新手同學的小禮物。
他遇到的打包問題簡單,實際解決后,也和我解決問題前的預計差不多。
開始遠程看他桌面前,商量用“騰訊會議”來遠程,我沒用過. 以前和同事遠程都是用TeamViewer,AnyDesk,向日葵,那時的同事沒人用"騰訊會議"。
因為確實第一次用么,確實不會用。結果我加入會議后,不知道怎么請求操縱對方桌面,這不就是一個菜單在哪里的問題么?
但是我第一次用,我應該不知道菜單在哪里。如果能找到菜單那么應該是在常見,顯眼的位置,或者和VS/IDEA比較像。
他居然質疑我不論是搞C++的還是其他IT行業,不知道怎么操作"騰訊會議"的遠程控制的菜單位置,這是基本的素質問題。
我不知道他咋能說出這樣的話。你是讓我幫你解決打包工程的問題,又不是你面試我。現在哥也不需要別人來面試我,沒需求啊。只要你讓哥看一下你演示的問題(不局限在C#打包這樣簡單的問題),哥立馬會給你分析一些可能的原因,再看哥做一些實驗來驗證想法,就能將問題解決掉,再將隨著實驗做的調試筆記轉成pdf傳給你,華麗的展示解決問題的思路和整個過程,你這輩子再也不會嫌棄哥不會操作"騰訊會議", 再也不會質疑哥的基本素質。
你會操作"騰訊會議",也就是你們同事之間都用這個,一個工具,用過一次就會。我現在用過一次,我也會了,5分鐘的事。這和素質有啥關系?
你能保證不同公司的人都用你知道的遠程桌面工具? 現在開源的遠程桌面工具也有很多,你都用過啊?我要是從開源的遠程工具上改一個特別版給我們一起用,我保證讓你不會用。
那你都會用"騰訊會議"來遠程演示了,那你自己遇到的C#簡單打包問題,你咋搞不定呢? 離你給我留私信都一個星期了,你都沒搞定,這和會不會操作"騰訊會議"有啥關聯?
哥在和你聊之前,也沒打包過c#的安裝程序。你交代了有償任務后,準備好環境后,1個小時就搞定了。你看看哥基本素質咋樣?
我的優點之一,就是分析問題能力強,解決問題能力強,思想火花落地能力強。
根本不需要,也不care誰說我基本素質有問題,特別是還要求著我幫忙的人,那我就更不care了。
筆記
看了遠程問題演示,問題主要可能有2個:
- 桌面快捷方式有可能沒指向C#寫的主EXE.
- C#運行時可能沒裝。
他給的打包工程,文件添加的鏈接位置和我本地不一樣,只能新建工程。
因為是簡單的工程,新建工程比修復他的打包工程還簡單。
后來發現,因為VS有bug, 他添加了錯誤組件無法去掉,導致編譯報錯,只能是新建工程,而不能修復工程。
C#我不常用,VS2022也不常用。
用VS2022準備C#環境用了一點時間。問題本身的解決時間并不長,主要時間花在驗證調試想法上了。
實驗過程
先在沒有dotnet6.0的設備上運行RTGCheckTool.exe,報錯如下
點擊是,從MS官網在線下載dotnet6.0的安裝包
https://dotnet.microsoft.com/zh-cn/download/dotnet/thank-you/runtime-desktop-6.0.36-windows-x64-installer?cid=getdotnetcore
順手將x86版本的dotnet6.0也下載下來備用。
https://dotnet.microsoft.com/zh-cn/download/dotnet/thank-you/runtime-desktop-6.0.36-windows-x86-installer?cid=getdotnetcore
運行下載好的dotnet6.0的安裝包 windowsdesktop-runtime-6.0.36-win-x64.exe, 先將運行環境裝好(用來測試程序本身是否可以在本地正常運行,如果正常,再打包)。
測試了一下,主程序運行起來了。
這說明,只需要在debug文件夾內的exe和dll基礎上,再安裝了windowsdesktop-runtime-6.0.36-win-x64.exe,程序就是可以運行的。
現在可以用VS2022打開打包工程Setup1.vdproj, 來圖形化配置打包參數了。
但是發現,用VS2022無法正常打開.vdproj這種工程文件。如果在選工程文件時,強行輸入*, 然后選vdproj, 也會打開失敗。
后來發現,VS2022安裝完,并沒有打開vdproj的能力,需要通過擴展,安裝打包插件才可以。
等有提示了,說關閉VS后,繼續安裝。就關掉VS, 等MS安裝工程的插件安裝完成。
先試試,是否VS2022能正常打開已經存在的setup1.vdproj
試了一下,ok.
現在決定,是在這個工程上改bug, 還是新建工程來打包?
因為這是有問題的工程,還是先新建工程打包后,安裝運行正常了,將打包流程弄清楚了。再從原始打包工程上改好了。
新建工程
就用第一個模板"Setup Project"就行。
嘗試編譯空的打包工程,可以編譯過。
將左視圖切到文件系統,用來添加打包的文件(在本地可以運行的文件集合exe, dll, 其他文件)
用鼠標,將要安裝到TARGET文件夾的文件,全部拖到左視圖的TARGET文件夾中。
用鼠標拖動的方法的好處,連子文件夾內的文件都添加進來了。
在用戶桌面上添加應用exe的快捷方式,直接添加不好指向exe, 參數不熟啊。
直接在文件樹應用文件夾中的主exe上右擊,選擇建立快捷方式。
這樣可以保證這個exe的快捷方式參數都是對的,不用自己填。
在快捷方式上左擊,在右邊視圖中的屬性窗口上改快捷方式的名稱為自己想要的中意名稱。
如果需要圖標,也可以自己選。
先將自己選中的圖標,拷貝到相對于安裝工程的目錄。然后改屬性Icon.
將圖標拖動到安裝工程的應用文件夾。
在主程序exe的快捷方式屬性中,點擊icon右邊的按鈕,瀏覽圖標位置,確定即可。
設置完圖標后,看到內容是Icon, 看不到圖標的具體路徑,不管他,這是VS做的不夠好,不管他。
將快捷方式由應用文件夾拖動到打包工程的桌面文件夾。
讓依賴的運行時程序安裝包在安裝時運行(如果發現運行時不能每次都安裝程序,就不要做這步)
實驗表明, windowsdesktop-runtime-6.0.36-win-x64.exe 不是每次都運行成功,導致安裝程序失敗,這不是我們能解決的問題。所以,windowsdesktop-runtime-6.0.36-win-x64.exe只推薦在用戶計算機上手工安裝一次,并不建議作為依賴的安裝程序包含在主安裝程序中。
這里只是說明如何給C#的打包程序添加安裝時,需要安裝依賴的安裝包后,才結束安裝的操作。
如果有自己的程序(保證不會更新系統DLL, 只是一些邏輯功能),需要在安裝時運行一下,可以用這種方法。
在應用文件夾中,拖入下載好的windowsdesktop-runtime-6.0.36-win-x64.exe
現在讓程序安裝拷貝操作后,運行windowsdesktop-runtime-6.0.36-win-x64.exe,將dotnet環境裝好后,再結束安裝。
切到自定義操作
在安裝環節,添加自定義操作
在自定義操作彈出的item對話框中,選中要在安裝結束前運行的dotnet6的runtime exe, 點擊OK添加。
那現在配置就完事了(需求已經滿足,拷貝文件到安裝文件夾,然后運行runtime.exe,再結束安裝)
關于”運行時安裝程序無法每次都安裝成功“的應對
可以在“Custom Actions/Install"中加入自己的程序,由自己的程序來檢測當前計算機是否由依賴,如果沒依賴,就運行同級目錄中的運行時安裝包,這樣控制的粒度就很細。也不用去探索VS是否提供檢測運行時是否存在的功能。
知識點
windows本身就有命令 dotnet, 可以列出DotNet運行時都裝了哪些。
將這個知識點包進自己的程序,就可以知道是否有自己關心的運行時是否已經安裝。
先檢測是否有dotnet命令,如果沒有,自然需要安裝。
如果有dotnet命令,再列出所有已經安裝的運行時,在里面找是否有自己關心的運行時。如果沒有,則需安裝。
這個方法好。
C:\Users\me>dotnet --list-runtimes
Microsoft.AspNetCore.App 7.0.20 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 8.0.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 8.0.19 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 9.0.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 9.0.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 6.0.36 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 7.0.20 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 8.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 8.0.19 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 9.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 9.0.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 6.0.36 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 7.0.20 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 8.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 8.0.19 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 9.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 9.0.8 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
嘗試打包
編譯成功了
========== 全部重新生成: 1 成功,0 失敗,0 已跳過 ==========
========== 重新生成 于 20:56:53 完成,耗時 19.678 秒 ==========
有些警告,來分析一下,是否礙事。
重新生成開始于 20:56:33...
------ Starting pre-build validation for project 'LsSetupV3' ------
WARNING: Unable to find dependency 'SYSTEM.SECURITY.CRYPTOGRAPHY.ALGORITHMS' (Signature='B03F5F7F11D50A3A' Version='6.0.0.0') of assembly 'ICSharpCode.SharpZipLib.dll'
WARNING: Unable to find dependency 'SYSTEM.SECURITY.CRYPTOGRAPHY.PRIMITIVES' (Signature='B03F5F7F11D50A3A' Version='6.0.0.0') of assembly 'ICSharpCode.SharpZipLib.dll'
WARNING: Unable to find dependency 'SYSTEM.NUMERICS.VECTORS' (Signature='B03F5F7F11D50A3A' Version='6.0.0.0') of assembly 'ICSharpCode.SharpZipLib.dll'
ICSharpCode.SharpZipLib.dll 這種是C#本身的DLL, 說沒找到啥依賴,這不怕,只要安裝拷貝后,先運行runtime.exe就ok, 不管這個,沒啥影響。
------ Pre-build validation for project 'LsSetupV3' completed ------
------ 已啟動全部重新生成: 項目: LsSetupV3, 配置: Debug ------
Building file 'D:\my_dev\all_mine\for_user\csdn_wq\LsSetup\LsSetupV3\LsSetupV3\Debug\LsSetupV3.msi'...
WARNING: File 'RTGCheckTool.exe' targeting 'x64' is not compatible with the project's target platform 'x86'
這是說exe是x64版本,但是打包工程是x86的,這不對,要改。
將打包工程改為x64的。
工程安裝前,自動卸載舊版本,為所有用戶安裝。
現在再嘗試打包,也是編譯過了,看一下警告,是否有潛在問題。
重新生成開始于 21:07:48...
------ Starting pre-build validation for project 'LsSetupV3' ------
WARNING: Unable to find dependency 'SYSTEM.COLLECTIONS.CONCURRENT' (Signature='B03F5F7F11D50A3A' Version='6.0.0.0') of assembly 'ICSharpCode.SharpZipLib.dll'
WARNING: Unable to find dependency 'SYSTEM.SECURITY.CRYPTOGRAPHY.PRIMITIVES' (Signature='B03F5F7F11D50A3A' Version='6.0.0.0') of assembly 'ICSharpCode.SharpZipLib.dll'
這個不需要管,只要安裝程序安裝了目標文件夾中的windowsdesktop-runtime-6.0.36-win-x64.exe,依賴就有了。
------ Pre-build validation for project 'LsSetupV3' completed ------
------ 已啟動全部重新生成: 項目: LsSetupV3, 配置: Debug ------
Building file 'D:\my_dev\all_mine\for_user\csdn_wq\LsSetup\LsSetupV3\LsSetupV3\Debug\LsSetupV3.msi'...
WARNING: Two or more objects have the same target location ('[targetdir]\npoi.ooxml.dll')
WARNING: Two or more objects have the same target location ('[targetdir]\npoi.ooxml.dll')
這個不用管,應用文件夾中沒有重復的文件,這應該是VS的bug.
沒有其他警告了。
試運行一下安裝程序,看看效果如何?
看工程屬性,找到生成好的安裝程序。
從時間上看,這是剛生成的,運行安裝程序看看效果。
先關掉VS, 再運行安裝程序。
如果已經安裝了程序,先卸載程序。發現windowsdesktop-runtime-6.0.36-win-x64.exe的每次安裝,選修復時,不是每次都成功。
安裝時,會先彈出運行時的安裝程序(windowsdesktop-runtime-6.0.36-win-x64.exe),選擇修復,等待修復完成。如果windowsdesktop-runtime-6.0.36-win-x64.exe安裝失敗,就會導致整個安裝程序失敗。
改一下安裝程序,不包括自定義動作安裝"windowsdesktop-runtime-6.0.36-win-x64.exe", 讓安裝程序和 windowsdesktop-runtime-6.0.36-win-x64.exe 分開,這樣,只需要安裝一次 windowsdesktop-runtime-6.0.36-win-x64.exe,setup程序可以安裝多次,這樣比較好。
重新打包,先安裝windowsdesktop-runtime-6.0.36-win-x64.exe, 只需安裝一次成功就行。再同一個計算機上,以后只安裝setup.msi.
如果不確定是否安裝了依賴,可以先安裝setup.msi, 等運行時報錯時,再安裝windowsdesktop-runtime-6.0.36-win-x64.exe。
可以看到,已經正常安裝完了。
桌面上也有了主程序的快捷方式。
運行一下試試。
C#主程序運行正常, ok了
到此,基于新工程模板建立的打包工程完全成功。
現在卸掉此工程,下一步來調試舊工程,看看問題出在哪里?
可以看到,控制面板中也有這個已經安裝的程序。將此程序卸載。
舊工程bug修復
先將工程改為x64版本
將打包的桌面文件夾的快捷方式先刪了,這個快捷方式不對,重新添加主程序exe的快捷方式。
先重新編譯一下工程,看看是否報錯
報錯了
重新生成開始于 21:47:13...
------ Starting pre-build validation for project 'Setup1' ------
ERROR: Unable to find source file 'D:\my_dev\all_mine\for_user\csdn_wq\RTGCheckToolHigher\bin\Debug\net6.0-windows\RTGCheckTool.pdb' for file 'RTGCheckTool.pdb', located in '[TARGETDIR]', the file may be absent or locked.
ERROR: Unable to find source file 'D:\my_dev\all_mine\for_user\csdn_wq\RTGCheckToolHigher\bin\Debug\net6.0-windows\MathNet.Numerics.dll' for assembly 'MathNet.Numerics.dll', located in '[TARGETDIR]'
ERROR: Unable to find source file 'D:\my_dev\all_mine\for_user\csdn_wq\RTGCheckToolHigher\bin\Debug\net6.0-windows\RTGCheckTool.deps.json' for file 'RTGCheckTool.deps.json', located in '[TARGETDIR]', the file may be absent or locked.
ERROR: Unable to find source file 'D:\my_dev\all_mine\for_user\csdn_wq\RTGCheckToolHigher\bin\Debug\net6.0-windows\NPOI.Core.dll' for assembly 'NPOI.Core.dll', located in '[TARGETDIR]'
原因,添加的文件都在另外一臺計算機上做的,這個工程是拷貝到本機的,所有這些文件的硬鏈接都不對了。
刪掉TARGET目錄中的所有文件。
刪的時候,如果有子文件夾,要刪除子文件夾中文件,然后在子文件夾的父目錄才能刪除子文件夾。
按照前文方式添加所有文件,用鼠標拖過來就行
做主程序RTGCheckTool.exe的快捷方式,改名,然后拖到桌面文件夾。見前文,不重復描述。
編譯工程,報錯
ERROR: 要在“系統必備”對話框中啟用“從與我的應用程序相同的位置下載系統必備組件”,必須將“Microsoft .NET Framework 4.7.2 (x86 和 x64)”項的文件“DotNetFX472\NDP472-KB4054530-x86-x64-AllOS-ENU.exe”下載到本地計算機。有關詳細信息,請參見 http://go.microsoft.com/fwlink/?LinkId=616018。
ERROR: 要在“系統必備”對話框中啟用“從與我的應用程序相同的位置下載系統必備組件”,必須將“Microsoft .NET Framework 4.7.2 (x86 和 x64)”項的文件“DotNetFX472\NDP472-KB4054530-x86-x64-AllOS-CHS.exe”下載到本地計算機。有關詳細信息,請參見 http://go.microsoft.com/fwlink/?LinkId=616018。
ERROR: 要在“系統必備”對話框中啟用“從與我的應用程序相同的位置下載系統必備組件”,必須將“.NET 運行時 6.0.36 (x64)”項的文件“net6coreruntime_x64\dotnet-runtime-6.0.36-win-x64.exe”下載到本地計算機。有關詳細信息,請參見 http://go.microsoft.com/fwlink/?LinkId=616018。
ERROR: General failure building bootstrapper
ERROR: Unrecoverable build error - 0x80004005
========== 全部重新生成: 0 成功,1 失敗,0 已跳過 ==========
========== 重新生成 于 21:53:54 完成,耗時 03.580 秒 ==========
這個工程開始加了Dotnet系統組件,應該刪了才行。因為系統組件通過windowsdesktop-runtime-6.0.36-win-x64.exe來單獨安裝。
切到啟動條件頁
將啟動條件中的DotNet組件刪掉,不需要。
只能刪掉一個,還剩一個無法刪除。
那重新編譯一下試試,還是報錯。
剩下的一個組件,不確定是否是這個原因編譯報錯。
從需求屬性中,可以原作者勾選的dotnet組件去掉
但是,啟動選項中還有Dotnet4.72的選項。
再嘗試編譯,ok了
Packaging file 'NPOI.Core.dll'...
Packaging file 'NPOI.OOXML.dll'...
========== 全部重新生成: 1 成功,0 失敗,0 已跳過 ==========
========== 重新生成 于 0:15:36 完成,耗時 19.460 秒 ==========
備注
到此,針對舊打包工程的分析,修復都已經完成。
VS打包工程是有bug, 這個我以前也發現過。如果發現打包工程有些設置,自己無意中設置錯了,也只能開一個新打包工程,沒有其他方法。
舊工程的問題主要是以下2點
- 添加了需求組件,這個不需要,通過手工先安裝windowsdesktop-runtime-6.0.36-win-x64.exe來解決,不需要添加啥Dotnet組件。
- 快捷方式要從exe本身來創建,然后改名,然后拷貝到打包工程的桌面文件夾中。而不要在桌面文件夾中直接建立exe的快捷方式。這種方法不是不行,而是我們不熟(快捷方式的參數咋填啊?你能保證填對么?),還是讓VS的UI來直接生成正確的快捷方式,我們來改名,移動位置好一些。
打包工程要注意編譯信息和運行時的報錯信息
不管打包工程是否編譯過,都要檢查所有警告信息,如果有不對的地方(e.g. x64的exe, 打包工程卻是x86的),要改正。
如果點擊快捷方式這種沒動靜,或者報錯,要針對具體情況分析,是缺少依賴(運行時沒安裝)?還是快捷方式沒指向exe本身?