启动离线ClickOnce应用程序并等待退出

7

我部署了一个ClickOnce Windows Forms应用程序(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.IsNetworkDeployed会返回falseApplicationDeployment.CurrentDeployment也是空的。这样我就失去了ClickOnce更新能力)。


我认为这是正确的行为。如果您正在调用ClickOnce“可执行文件”,则会检查更新。但据我所知,此行为位于生成的引导程序中。然后将调用真正的可执行文件。我想稍后研究一下这种行为。一个想法:获取“真实”的进程并等待其退出? - Herdo
@Herdo - 这可以通过 System.Reflection.Assembly.GetEntryAssembly().Location; 轻松实现,并且可以正常工作。然而,我的应用程序是设计为从另一个应用程序调用的,不会直接启动。如果我这样做,我将失去自更新功能,这是使用 ClickOnce 的主要原因。 - Jürgen Steinblock
2个回答

2
我的建议是在应用程序A中使用互斥锁,并让应用程序B检查和等待它。从我的角度来看,这是最清晰的方式。
应用程序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();

这似乎是一个不错的解决方案,我可以使用 new FileInfo(fileName).FullName 作为互斥体名称。这将允许我从多个 App B 实例启动多个 App A 实例。即使 App A 崩溃,这也不会成为问题,因为我已经在 App B 中实现了一个“等待 App A...取消”对话框。 - Jürgen Steinblock
我猜这个解决方案不能应用于非我自己开发的 ClickOnce 应用程序? - Mike

1
问题在于启动appref-ms进程实际上并没有启动应用程序,而是启动了部署清单,然后才启动应用程序本身,因此你启动的进程会立即退出。
如果你知道应用程序的名称(我假设你知道),你可以添加一个检查来查看何时已经启动了你的应用程序,例如:
string myAppName = "YourAppName";
DateTime startTime = DateTime.Now;
int newProcessId = 0;
List<int> runningProcessIds = new List<int>();

//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");

你说得对,我缩短了示例代码,正确的应该是 var process = Process.Start(location, uri); process.WaitForExit(); 问题与 ClickOnce 相关,因为我没有启动一个 exe 文件,而是一个 appref-ms 文档,所以 process.HasExited 的值为 true。如果是一个 exe 文件,相同的代码确实会等待进程退出。 - Jürgen Steinblock
这个方案可行,但我还必须找到特定的MyApp实例,因为它可以运行多次。我可以在运行Process.Start(...)之前和之后调用GetProcessByName,并找出哪一个是新的,或者使用Process.StartTime来找到正确的实例。 - Jürgen Steinblock
好的,我已经更新了我的答案,包括如何实现这一点。 - Matt Wilko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接