17

TL;博士

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


细节

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

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

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

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

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

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

4

4 回答 4

6

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

于 2012-09-27T14:21:02.653 回答
6

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

你像这样修复它:

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

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

于 2012-09-27T14:00:56.500 回答
2

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

Windows 有几个层,在这种情况下,两个有趣的层是Windows Shell API 和系统服务API。您正在使用Process.Start()一种将ShellExecuteEx在 Windows Shell 中调用的方式。Windows Shell 在 Windows 之上提供了一个抽象,您在其中有一个桌面(实际上是某个磁盘上的一个文件夹),并且文件被视为带有图标和动词的文档,以对这些文档进行操作。在您的情况下,您使用的是Open动词。

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

在 Windows 7 中,您可以在Control Panel > Programs > Default Programs > Set Associations检查和修改文件关联。我怀疑如果.PDF缺少与扩展相关的程序,您可能会得到FileNotFoundException,但我尚未验证。

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

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

于 2012-09-27T14:40:23.540 回答
0

您可以使用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);
于 2012-09-27T15:30:32.717 回答