启动脱机ClickOnce应用程序并等待退出

我已经部署了ClickOnce Windows窗体应用程序(App A)

另一个应用程序(App B)以文件名作为参数启动App A. 我使用此代码执行此操作

var basePath = Environment.GetFolderPath(Environment.SpecialFolder.Programs); var location = String.Format(@"{0}\{1}\{2}\{3}", basePath, "MyCompany", "MyProduct", "MyApp.appref-ms"); var fileName = @"c:\temp\somefile.ext"; var uri = new Uri(fileName).ToString(); Process.Start(location, uri); 

App A从AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData[0]获取文件名并显示内容。

这就像一个魅力。 但是,现在我希望App B等待App A退出。 但是对Process.WaitForExit()的调用会立即返回。

有没有办法打开ClickOnce应用程序并等待它退出? 如果有必要,我可以更改应用程序的运行方式,但要求是我需要将应用程序作为ClickOnce应用程序运行(我知道在我的用户配置文件AppData\Local\Apps\2.0\文件夹中的某个地方存在exe并且可以直接启动但是如果我这样做,则ApplicationDeployment.IsNetworkDeployedfalseApplicationDeployment.CurrentDeployment为null。在此我松开了ClickOnce更新function)。

我的建议是在App A中使用Mutex ,然后让App B检查并等待它。 从我的角度来看,这是最干净的方式。

App A在启动时执行此操作:

  private static Mutex mutex; public static void Main() { // if you want your app to be limited to a single instance // across ALL SESSIONS (multiple users & terminal services), then use the following line instead: // string mutexName = string.Format("Global\\{0}", ProgramInfo.AssemblyGuid); var mutexName = string.Format("Local\\{0}", SOME_SHARED_GUID); mutex = new Mutex(true, mutexName, out singleInstance); if (singleInstance == false) { // that means your app has more than one instance running // you need to decide what to do here. } // rest of initialization code Application.Run(); // release the mutex so App B can continue mutex.ReleaseMutex(); } 

和App B等待释放互斥锁:

 Process.Start(location, uri); Thread.Sleep(5000); // give it 5 seconds or so to check for updates and start var mutexName = string.Format("Local\\{0}", SOME_SHARED_GUID); mutex = new Mutex(false, mutexName); mutex.WaitOne(); 

问题是启动appref-ms进程实际上并没有启动应用程序它启动部署清单,然后启动应用程序本身,因此您开始的进程会立即退出。

如果您知道名称(我假设您这样做),您可以添加一个检查以查看应用程序何时启动,如下所示:

 string myAppName = "YourAppName"; DateTime startTime = DateTime.Now; int newProcessId = 0; List runningProcessIds = new List(); //find all the running processes and record their Ids foreach (void proc_loopVariable in Process.GetProcessesByName(myAppName)) { proc = proc_loopVariable; runningProcessIds.Add(proc.Id); } //start the new process Process.Start(location); //wait for the new application to be started while (!(Process.GetProcessesByName(myAppName).Count != runningProcessIds.Count)) { //timeout if we have not seen the application start if ((DateTime.Now - startTime).TotalSeconds > 30) break; } //loop through all the running processes again to find the id of the one that has just started foreach (void proc_loopVariable in Process.GetProcessesByName(myAppName)) { proc = proc_loopVariable; if (!runningProcessIds.Contains(proc.Id)) { newProcessId = proc.Id; break; } } //wait for the application to finish Process.GetProcessById(newProcessId).WaitForExit(); Debug.WriteLine("Finished");