简体   繁体   English

System.Diagnostics.Process.Start()奇怪的行为

[英]System.Diagnostics.Process.Start() strange behaviour

I have an application that uses Process.Start(string Filename) to open up a file. 我有一个使用Process.Start(字符串Filename)打开文件的应用程序。 This method overload will cause the system to invoke the appropriate application based on the filename extension. 此方法重载将导致系统根据文件扩展名调用相应的应用程序。 In my case, it will typically be a WORD, PPT, PDF, JPG etc... Some type of viewable document. 就我而言,它通常是WORD,PPT,PDF,JPG等......某种类型的可查看文档。 Ultimately, I need to launch the process and then later in the application I need to do something with the MainWindowHandle value. 最后,我需要启动该过程,然后在应用程序中我需要使用MainWindowHandle值执行某些操作。

I've found at least three different cases that cause Process.Start(string filename) to return different ways... 我发现至少有三种不同的情况会导致Process.Start(字符串文件名)返回不同的方式...

For the first and second cases below, assume I'm opening up two .pdf files (but the same thing appears to happen if I was opening two .ppt or two .doc files as well)... 对于下面的第一个和第二个案例,假设我打开两个.pdf文件(但是如果我打开两个.ppt或两个.doc文件,似乎也会发生同样的事情)......

Case 1: If AcroRd32 isn't running and I do something like.. 案例1:如果AcroRd32没有运行,我做了类似的事情..

Process p = Process.Start("yada.pdf");
p.WaitForInputIdle();
p.Refresh();

things work as expected. 事情按预期工作。 The value p.MainWindowHandle is populated correctly. 正确填充值p.MainWindowHandle。 No problem with this case. 这种情况没问题。

Case 2: Now assume at the time of the call to Process.Start() AcroRd32 is already running on a previously opened pdf file. 情况2:现在假设在调用Process.Start()时AcroRd32已经在先前打开的pdf文件上运行。 Now things get weird. 现在事情变得怪异了。 Referring to the code below (some error-checking logic removed for clarity), after the call to Process.Start() the value of p.MainWindowHandle is zero (even though the window is created), and p.MainWindowTitle is empty. 参考下面的代码(为清楚起见,删除了一些错误检查逻辑),在调用Process.Start()之后,p.MainWindowHandle的值为零(即使创建了窗口),并且p.MainWindowTitle为空。 Then I sleep for 1 second and the handle is still zero, but the mainwindowtitle is now populated (even though I did NOT call p.Referesh() after the sleep. Each of the trace statements that have "<<<<" in the comments are printed at runtime. 然后我睡了1秒钟,手柄仍然为零,但是主窗口现在已经填充(即使我没有在睡眠后调用p.Referesh()。每个跟踪语句中都有“<<<<”注释在运行时打印。

Process p = Process.Start("SomeFileName.pdf");
p.WaitForInputIdle();
p.Refresh();
if (p.MainWindowHandle == 0)
    DebugTrace("MainWindowHandle is zero, why??");   //<<<<
if (p.MainWindowTitle.Length == 0)
    DebugTrace("MainWindowTitle is null");           //<<<<
Thread.Sleep(1000);
if (p.MainWindowHandle == 0)
    DebugTrace("MainWindowHandle is still zero.");   //<<<<
if (p.MainWindowTitle.Length == 0)
    DebugTrace("MainWindowTitle is null");
else
    DebugTrace("MainWindowTitle: " + p.MainWindowTitle);  //<<<<

I'm sure this has something to do with the fact that AcroRd32 is already running, but I have no control over that and I do need to get the value of p.MainWindowHandle. 我确定这与AcroRd32已经运行的事实有关,但是我无法控制它,我确实需要获得p.MainWindowHandle的值。 Any ideas how to handle this? 任何想法如何处理这个?

Case 3: Then onto the third case: in some cases, Process.Start() will return null even when it successfully opens the file. 情况3:然后进入第三种情况:在某些情况下,即使成功打开文件,Process.Start()也将返回null。 I found this to be the case with .jpg files, but I'm sure that just depends on the application that has been assigned to the .jpg extension. 我发现这是.jpg文件的情况,但我确信这取决于已分配给.jpg扩展名的应用程序。 The Process.Start("file.jpg") returns null if the application is "Windows Photo Viewer" but if I change that to be "Paint" it doesn't return null. 如果应用程序是“Windows Photo Viewer”,Process.Start(“file.jpg”)将返回null,但如果我将其更改为“Paint”,则它不会返回null。 What's up with that? 那是怎么回事? And how can I get the handle then? 那我该怎么办呢?

Ok, all done, sorry for the detail, but hopefully I'm explaining the situation(s) I'm trying to work through! 好的,一切都完成了,抱歉细节,但希望我正在解释我正在努力解决的情况!

I suspect that windows start a new process with acroRd32, which then passes along the given filepath to the running instance and then shuts down. 我怀疑windows使用acroRd32启动一个新进程,然后acroRd32将给定的文件路径传递给正在运行的实例,然后关闭。

This is how it is usually done for avoiding multiple instance of a program... 这是通常用于避免程序的多个实例的方式......

You can't depend on MainWindowHandle that Process.Start returns. 您不能依赖Process.Start返回的MainWindowHandle。 As you mentioned, it doesn't return it when the file gets opened by an alreadly running application. 正如您所提到的,当文件被一个运行良好的应用程序打开时,它不会返回它。 Since Windows Vista, MS added ReStart Manager, a new api that can give your locking processes on a given file. 自Windows Vista以来,MS添加了ReStart Manager,这是一个新的api,可以在给定文件上提供锁定进程。 https://msdn.microsoft.com/en-us/magazine/cc163450.aspx https://msdn.microsoft.com/en-us/magazine/cc163450.aspx

My approact to the problem was to try Process.Start's MainWindowHandle and the locking handle ReStart manager returns. 我对这个问题的反应是尝试Process.Start的MainWindowHandle和锁定句柄ReStart管理器返回。 There's an example code from MSDN magazine. MSDN杂志有一个示例代码。 https://github.com/andrewchaa/PopOpen/blob/master/Pop.Cs/InUseDetection.cs https://github.com/andrewchaa/PopOpen/blob/master/Pop.Cs/InUseDetection.cs

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM