在Windows中,当我在Windows资源pipe理器中双击某个文件时会发生什么?

TL; DR

当用户在Windows资源pipe理器中双击或select一个文件并按Enter键时,正在执行的低级内核和操作系统调用是什么?


细节

这可能看起来像一个相当奇怪的问题,但我很好奇从Windows资源pipe理器打开文件的“细节”的细节。

具体来说,我想知道的是,当用户在Windows资源pipe理器中双击或select一个文件并按Enter键时,正在执行的低级内核和OS调用。

我之所以问,是因为我有一个应用程序,允许用户根据存储在数据库中的元数据来浏览和search文件。 当用户点击我提供的Openbutton时,我启动一个进程,其中根文件是所选文件的path。 另外,值得一提的是这些文件在networking共享上。

这已经工作了很多年,然而,最近我的公司已经迁移到一个新的活动目录服务器,现在应用程序被打破了极less数用户(1-2%)。真奇怪的是,这些用户无法打开这个文件从我的应用程序,但他们可以浏览到的位置,并从Windows资源pipe理器打开它。 当我的应用程序试图打开文件时,会得到一个非常通用的exception,指出找不到该文件。

我三重检查了应用程序正在使用的path(对于多个文件),path并不正确。 我已经validation过我的用户在打开文件之前已经连接到这些networking驱动器。 一切安装正确,应该工作,但我的应用程序(或System.Process )不能“看到”或打开这些文件。

什么是Windows资源pipe理器应用程序做的不同于在应用程序中使用System.Process


对于那些在回答之前必须有代码的人,这里是我用来打开文件的非常简洁的代码。 再说一遍,这已经工作了好几年了,就我所知,就是让Windows从.Net内部打开一个文件。

 //From within my Button-Click Event... string file = e.Cell.Value.ToString(); try { Process p = new Process(); p.StartInfo.FileName = file; p.StartInfo.Verb = "Open"; p.Start(); } catch (Exception ex) { MessageBox.Show("A problem has occurred while trying to open the doccument." + "Please make sure that the file below exists and that you have permission " + "to view it." + Environment.NewLine + Environment.NewLine + file + Environment.NewLine + "---------------" + Environment.NewLine + ex.Message ); //ex.Message states "The system cannot find the file specified" } 

还有一件事。 我在SO上发现了这个问题 ,但是它不适用于这个问题。 我的应用程序只是试图打开PDF和一些工程制图文件。 没有什么奇特的,它不应该要求pipe理员访问。 此外,我不相信任何用户身份validation应该是必需的,因为大多数用户从来没有得到这个消息,他们已经通过login和浏览networking位置在networking上validation自己。

当用户在Windows资源管理器中双击或选择一个文件并按Enter键时,正在执行的低级内核和操作系统调用是什么?

你可以自己测试一下。 下面是我做的:一个C#程序代码示例

 class Program { static void Main(string[] args) { } } 

现在,您可以从预先定位的位置运行此应用程序。 然后,您可以使用SysInternals中的ProcMon应用程序来观察低级调用。 这里是ProcMon在我的机器上生成的csv文件的快照。 我已经把过滤器只包含文件的path ,这是c:\test.exe

 "Time of Day","Process Name","PID","Operation","Path","Result","Detail" "14:57:55.3495633","Explorer.EXE","2568","CreateFile","C:\Test.exe","SUCCESS","Desired Access: Generic Read, Disposition: Open, Options: Open Requiring Oplock, Attributes: N, ShareMode: Read, AllocationSize: n/a, OpenResult: Opened" "14:57:55.3498808","Explorer.EXE","2568","FileSystemControl","C:\Test.exe","SUCCESS","Control: FSCTL_REQUEST_FILTER_OPLOCK" "14:57:55.3507711","Explorer.EXE","2568","CreateFile","C:\Test.exe","SUCCESS","Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened" ... 

csv的完整版本在pastebin上可用。 csv文件中的每一行对应一个低级别的调用,另外还有其他的绒毛由于严格的路径过滤而被排除。

一个非常常见的失败模式,出现在您的代码中,不正确地设置ProcessStartInfo.WorkingDirectory。 程序的一个子集依赖于资源管理器将默认的工作目录设置为包含该文件的目录,并在未设置时跳过。 他们会做一些不明智的事情,比如试图打开一个配置文件而不指定完整的路径名,这只有在工作目录设置正确的情况下才有效。

你解决这个问题:

 Process p = new Process(); p.StartInfo.FileName = file; p.StartInfo.WorkingDirectory = System.IO.Path.GetDirectoryName(file); p.Start(); 

这假设你不会犯同样的错误,不指定文件的完整路径名。

你“TL; DR”的问题是简单的,但我不确定回答这个问题是否能解决你的问题。 Hans Passant的答案可能更有用。 不过我会尽量提供一点信息。

Windows有几个层次,在这种情况下,两个有趣的层次是Windows Shell API和System Services API。 您正在使用Process.Start()方式,将在Windows Shell中调用ShellExecuteEx 。 Windows Shell在Windows的顶部提供了一个抽象(在某些磁盘上,这实际上是一个文件夹),文件被视为带有图标和动词的文档来操作这些文档。 在你的情况下,你正在使用Open动词。

Windows Shell非常复杂,可以扩展,因此ShellExecuteEx为特定路径和动词所做的事情很容易回答。 这取决于在本地机器上注册的内容。 但是,如果该文件是一个PDF文件,并且动词是Open那么可以预料,shell将运行与注册表中的.PDF扩展名关联的任何应用程序。

在Windows 7中,您可以在控制面板 > 程序 > 默认程序 > 设置关联中检查和修改文件关联 。 我怀疑,如果与.PDF扩展名关联的程序丢失,您可能会得到FileNotFoundException但我没有验证。

如果shell决定应该执行一个应用程序,它将在某个时候调用System Services层,并使用CreateProcess函数来创建一个新的进程。 对于PDF文件(取决于.PDF的注册),将创建一个使用单个命令行参数(指定的文件)执行Acrobat.exe的进程。

要解决这个问题,你可以在命令提示符下编写file.pdf文件(该文件应该存在),看看shell是否能够打开一个PDF文件。

你可以尝试使用FileSystemInfo.FullName这样的事情吗?

 string file = e.Cell.Value.ToString(); var fileInfo = new FileInfo(Path.Combine(System.IO.Path.GetDirectoryName(file) + file)); if (!fileInfo.Exists) { throw new FileNotFoundException(fileInfo.FullName + " was not found"); } System.Diagnostics.Process.Start(fileInfo.FullName);