[英]How to start an exe from a .NET Windows Service for updating the service
我有一個Windows服務,我希望它可以自動進行無提示更新。 我開始使用wyBuild來實現它,但是遇到了一些問題,因此決定嘗試構建自己的。 我已經編寫了一個獨立的exe文件,可以調用它來執行更新過程:檢查包含更新的新zip文件,下載該文件,解壓縮,停止Windows服務,從zip復制文件,然后重新啟動該服務。 當我從命令行運行該exe時,它運行良好,並且編寫起來並不難。
但是,現在我希望該服務(正在更新同一服務)能夠將其安裝到updater exe中進行更新。 我首先嘗試了Process.Start:
var proc = Process.Start(pathToUpdaterExe);
proc.WaitForExit(60000);
這稱為更新程序,但是當更新程序停止服務時,進程將被終止,更新程序將停止。 我做了一些搜索,聽起來解決方案是使用單獨的AppDomain。 這就是我現在所擁有的:
Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
Evidence objEvidence = new System.Security.Policy.Evidence(baseEvidence);
AppDomainSetup setup = new AppDomainSetup();
var updateDomain = AppDomain.CreateDomain("updateDomain", objEvidence, setup);
updateDomain.ExecuteAssembly(updater);
AppDomain.Unload(updateDomain);
但是,現在出現錯誤System.IO.IOException:“該進程無法訪問文件'C:\\ Program Files(x86)\\ Company \\ Service \\ Service.dll',因為它正被另一個進程使用”復制新的Service.dll
同樣,我已經停止了該服務。 我已經通過日志記錄確認了這一點。 我無法想象Service.dll仍會鎖定,因此我添加了代碼來檢查鎖定了什么:
public static IEnumerable<Process> GetProcessesLocking(string filePath)
{
var result = new List<Process>();
result.Clear();
var processes = Process.GetProcesses();
foreach (Process proc in processes)
{
try
{
if (proc.HasExited) continue;
foreach (ProcessModule module in proc.Modules)
{
if ((module.FileName.ToLower().CompareTo(filePath.ToLower()) == 0))
{
result.Add(proc);
break;
}
}
}
catch (Exception ex)
{
Log(ex.ToString());
Log("There was an error checking " + proc.ProcessName );
}
}
return result;
}
但是,此代碼表明dll上沒有任何鎖(結果為空,並且未記錄任何內容指示錯誤)。
我懷疑我遇到了某些UAC問題,這是IOException的真正原因。 Windows服務作為LocalSystem運行。 所有要問的問題:我應該如何從Windows服務運行更新exe,以便它有權復制c:\\ Program Files中的文件?
更新資料
正如評論和答案所暗示的,Process.Start可以工作,但有一些細微差別。 您必須啟動cmd.exe並使用它來啟動更新程序。 我還發現我無法使用更新程序exe的完整路徑,因此需要設置UseShellExecute = false。 這是我從.NET服務啟動更新程序的最終工作代碼:
var cmd = "/c start updater.exe";
var startInfo = new ProcessStartInfo("cmd.exe");
startInfo.Arguments = cmd;
startInfo.WorkingDirectory = AssemblyDirectory;
startInfo.UseShellExecute = false;
var proc = Process.Start(startInfo);
我做了這個確切的事情-使用一種更簡單的方法(有些人可能說kludgy)。 服務:
批處理命令:
像發條一樣工作。 ping是可靠的5秒延遲-讓服務在復制文件之前關閉。
編輯 :
只是為了完整性-我意識到按批處理ping是127.0.0.1而不是128.0.0.1,因此我編輯了此答案以反映這一點。 我想這兩個都可以-但是128.0.0.1 ping超時,其中127.0.0.1解析為“我”。 由於我只是將其用作窮人的延誤,因此無論哪種方式都可以達到目的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.