我有一个Windows服务,我希望自动并静默更新。我开始使用wyBuild来实现它,但是它遇到了一些问题,并决定尝试构建自己的。我写了一个独立的exe,可以调用来执行更新过程:检查新的zip文件与更新,下载,解压缩,停止Windows服务,从zip复制文件,然后重新启动服务。当我从命令行运行它时,这个exe工作正常,并且写起来并不是很难。
但是,现在我希望服务(同一个正在更新)向updater exe进行shell更新。我首先尝试了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并使用 it 启动更新程序。我还发现我无法使用updater 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);
答案 0 :(得分:1)
我做了这件事 - 使用更简单(有些人可能会说是kludgy)的方法。服务:
批处理命令:
像钟表一样工作。 ping是一个可靠的5秒延迟 - 让服务在复制文件之前关闭。
修改强>:
为了完整性 - 我意识到批处理cmd正在ping 127.0.0.1而不是128.0.0.1,所以我编辑了这个答案来反映这一点。我想要么工作 - 但128.0.0.1 ping超时,其中127.0.0.1解析为“我”。由于我只是将它用作穷人的延迟,因此无论如何都可以达到目的。