在 Windows 中,当我在 Windows 资源管理器中双击一个文件时会发生啥?

Posted

技术标签:

【中文标题】在 Windows 中,当我在 Windows 资源管理器中双击一个文件时会发生啥?【英文标题】:Within Windows, what explicitly happens when I double-click on a file in Windows Explorer?在 Windows 中,当我在 Windows 资源管理器中双击一个文件时会发生什么? 【发布时间】:2012-09-19 07:54:55 【问题描述】:

TL;DR

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


详情

这似乎是一个相当奇怪的问题,但我很好奇从 Windows 资源管理器打开文件的细节。

具体来说,我想知道的是当用户在 Windows 资源管理器中双击或选择文件并按下 Enter 键时正在执行的确切的低级内核和操作系统进程。

我问的原因是因为我有一个应用程序允许用户根据存储在数据库中的元数据浏览和搜索文件。当用户单击我提供的Open 按钮时,我会启动一个进程,其中根文件是已选择文件的路径。此外,值得一提的是,这些文件位于网络共享上。

这已经工作了很多年,但是,最近我的公司已经迁移到一个新的 Active Directory 服务器,现在该应用程序对于极少数用户 (1-2%) 来说是损坏的。真正奇怪的是这些用户无法从我的应用程序中打开此文件,但他们可以浏览到该位置并从 Windows 资源管理器中打开它。当我的应用程序尝试打开该文件时,它会收到一个非常通用的异常,指出找不到该文件。

我已经三次检查了应用程序正在使用的路径(对于多个文件)并且路径不正确。在打开文件之前,我已验证我的用户已连接到这些网络驱动器。一切都设置正确并且应该可以工作,但我的应用程序(或System.Process)无法“看到”或打开这些文件。

Windows 资源管理器应用程序与在应用程序中使用 System.Process 有何不同?


对于那些在回答之前必须有代码的人,这里是我用来打开文件的非常简洁的代码。同样,这已经工作了多年,据我所知,这就是让 Windows 从 .Net 中打开文件的方式。

//From 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 上找到了this question,但它不适用于/不应该适用于这个问题。我的应用程序只是试图打开 PDF 和一些工程图文件。没什么特别的,它不应该需要管理员访问权限。此外,我认为不需要任何用户身份验证,因为大多数用户从未收到此消息,并且他们已经通过登录并浏览到网络位置在网络上验证了自己。

【问题讨论】:

在 PC 级别出现故障的客户端之间是否存在共性?它们与正在运行的操作系统是否在不同的操作系统上? 很难说。我们的 IT 确实在 AD 迁移之前进行了大规模的 Windows 7 转换。获得新用户帐户的用户和许多准备升级 PC 或接近计划时间的用户都获得了装有 Win 7 的新 PC。遇到问题并与我交谈最多的一位经理仍然卡住了与 Windows XP。但是,过去在这台 PC 上它总是对他有效——他刚刚在新的 AD 域上获得了一个新帐户以开始使用。我们已经三次检查了他的权限。他可以浏览到该位置并打开这些文件,但我的应用程序不能? 它是否只在 PDF 上失败?您在使用 Acrobat 吗? Acrobat 不能很好地与 .NET 配合使用。它是单个 .exe,从外部一次只能打开一个文件。如果它处于活动状态,有时会不响应。尝试在 .NET 中托管视图充其量是有问题的——因为它会吃掉按键事件。 谢谢布拉姆。首先,我试图告诉内核打开文件——而不是应用程序,因此调用System.Process。也没有该项目的预览。还有其他文件类型(我认为是.dwg),我可以让这些用户之一尝试打开其中一个。不过,这可能有点问题,因为并不是每个人都使用 dwg,而且他可能没有合适的应用程序来打开它。事实上,我的电脑上什至没有 dwg 视图。 ...这可能是 Acrobat 的问题,但我对此表示怀疑。我有另一个应用程序正在使用大约三倍的用户(数百个),并且该应用程序对 PDF 使用了相同的启动过程。该应用程序已经存在了 6 年,并且可以在 XP、Vista、MS Server 2000+ 和 Windows 7 上运行,没有任何问题。唯一的区别是正在打开的文件存储在本地用户Documents 文件夹中。 【参考方案1】:

当用户在 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 文件中的每一行都对应一个低级调用,此外还有其他由于路径上的严格过滤而被排除的绒毛。

【讨论】:

【参考方案2】:

您的代码中存在的一种非常常见的故障模式是未正确设置 ProcessStartInfo.WorkingDirectory。一部分程序依赖于资源管理器将默认工作目录设置为包含文件的目录,并在未设置时失败。他们会做一些不明智的事情,比如在不指定完整路径名的情况下打开配置文件,只有在工作目录设置正确的情况下才有效。

你这样修复它:

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

假设您不会犯同样的错误,即未指定 file 的完整路径名。

【讨论】:

file 完全合格。我将进行此更改并发布它。谢谢! 另外,当您从 Windows 资源管理器启动文件时,这是否有效? 答案中明确提到:programs rely on Explorer setting the default working directory【参考方案3】:

您的“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 决定执行一个应用程序,它会在某个时候调用系统服务层并使用CreateProcess 函数来创建一个新进程。对于 PDF 文件(取决于 .PDF 的注册),将创建一个使用单个命令行参数(您指定的文件)执行 Acrobat.exe 的进程。

要解决此问题,您可以在命令提示符处写入 file.pdf(该文件应该存在)并查看 shell 是否能够打开 PDF 文件。

【讨论】:

【参考方案4】:

你能用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);

【讨论】:

以上是关于在 Windows 中,当我在 Windows 资源管理器中双击一个文件时会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章

当我在 Windows 上的 HID 设备上执行 ReadFile() 时会发生啥?

当我在 Windows 7 中运行“first”或“take”方法时 pyspark 崩溃

当我在 Windows 终端 http-server 上键入命令时

当我在 Windows 中编辑代码但在 Linux 中构建和运行代码时如何使用 git 进行版本控制(使用 pycharm)

如何在Windows中写入csv文件[重复]

C#,当我在 Windows 窗体应用程序中发送电子邮件时,图像显示为空白 [重复]