.NET中的Application.Restart如何工作?

6

这个问题并不是关于如何重新启动一个应用程序。我已经通过使用Mutex和辅助启动器应用程序来实现了。在使用Application.Restart遇到一些问题后,我不得不采取这种方式。

无论如何,由于我不熟悉IL,我想知道是否有人可以解释一下Application.Restart的工作原理。它调用运行时,但运行时具体做了什么呢?它如何关闭现有实例,并如何知道何时启动新实例?

1个回答

8

...不熟悉IL...

您是否考虑使用反编译工具(Reflector,dotPeek)或者更好的方法是使用.NET框架的参考源代码

无论如何。

初步看来它执行以下操作:

在以下所有情况下,当前实例均使用Application.ExitInternal()终止。这是公共Application.Exit()方法的要点,省略了一些安全检查/断言。
查看是否可以确定Assembly.GetEntryAssembly()。如果为null,则调用Application.Restart()很可能是从非托管代码中完成的,并且该操作会向调用者抛出NotSupportedException
查看当前进程是否为ieexec.exe,如果是,则使用它重新启动应用程序(有关ieexec.exe的更多信息,请参见here)。实际上,这几乎也是对ieexec.exe进行Process.Start()调用,但是命令行参数不是通过Environment.GetCommandLineArgs()(请参见下文)收集的,而是通过读取APP_LAUNCH_URL应用程序域数据收集的。
查看应用程序是否为ClickOnce应用程序(ApplicationDeployment.IsNetworkDeployed),如果是,则调用CLR内部本机代码来(重新)启动它:CorLauncApplication。唯一公开可用的与CLR本机部分相似的源代码是共享源CLI(sscli),它基于.NET 2.0框架,也部分不完整。它包含该函数的定义(clr\src\vm\hosting.cpp),但它只是一个存根。最终将使用某种方法重新启动进程(例如Win32的CreateProcess API)。
否则:应用程序是“常规”的.NET应用程序。使用Environment.GetCommandLineArgs()重新创建原始命令行,并使用Process.Start(Application.ExecutablePath)重新启动应用程序。
使用 Application.Exit 机制尝试结束当前实例可能是您发现其不可靠的原因。取消发送关闭事件的窗体可能会中断它。还请参见 this SO 问题。

哎呀,你的回答比我的好太多了,我可能就删掉我的吧 :(. 给你点赞,先生! - Scott Chamberlain
@Christian.K:谁调用了 Process.Start(Application.ExecutablePath) - joe
@joe 在函数返回之前,调用了 Application.Restart() 的线程是最后执行的事情。 - Scott Chamberlain
感谢您的澄清。我不确定为什么我没有使用反编译器。无论如何,您是否认可在辅助启动应用程序中使用互斥锁作为一种可接受的方法? - Raheel Khan
这完全取决于你的应用程序是如何部署的,如果你使用ClickOnce,你可以直接调用Update(然后在此之后调用Application.Restart(),实际上这种用例在MSDN页面上有说明)。但是对于大多数情况,我会使用单独的更新器存根应用程序来完成。 - Scott Chamberlain

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