C# 在Windows中,双击Windows资源管理器中的文件时会发生什么情况?
TL;DR 当用户在Windows资源管理器中双击或选择一个文件并按下C# 在Windows中,双击Windows资源管理器中的文件时会发生什么情况?,c#,.net,windows,windows-explorer,C#,.net,Windows,Windows Explorer,TL;DR 当用户在Windows资源管理器中双击或选择一个文件并按下Enter键时,正在执行的底层内核和操作系统进程是什么 详细信息 这似乎是一个相当奇怪的问题,但我很好奇从Windows资源管理器打开文件的细节 具体地说,我想知道的是当用户双击或选择文件并在Windows资源管理器中按下Enter键时执行的确切的底层内核和操作系统进程 我问这个问题的原因是因为我有一个应用程序,允许用户根据存储在数据库中的元数据来浏览和搜索文件。当用户单击我提供的Open按钮时,我会启动一个进程,其中根文件
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"
}
还有一件事。我发现是这样,但它不适用于这个问题。我的应用程序只是试图打开PDF和一些工程图纸文件。没什么特别的,也不需要管理员权限。此外,我认为不需要任何用户身份验证,因为大多数用户从未收到此消息,并且他们已经通过登录和浏览网络位置在网络上验证了自己。代码中存在的一种非常常见的故障模式是未正确设置ProcessStartInfo.WorkingDirectory。程序的一个子集依赖于资源管理器将默认工作目录设置为包含文件的目录,如果未设置该目录,则会被忽略。他们会做一些不明智的事情,比如在没有指定完整路径名的情况下尝试打开配置文件,只有在工作目录设置正确的情况下才有效 您可以这样修复它:
Process p = new Process();
p.StartInfo.FileName = file;
p.StartInfo.WorkingDirectory = System.IO.Path.GetDirectoryName(file);
p.Start();
它假设您不会犯同样的错误,没有指定文件的完整路径名
当用户在Windows资源管理器中双击或选择文件并按下Enter键时,执行的底层内核和操作系统调用是什么
你可以自己测试。我是这样做的:一个示例C#程序代码
class Program
{
static void Main(string[] args)
{
}
}
现在,您可以从预先定义的位置运行此应用程序。然后,您可以使用SysInternals中的应用程序来观察低级调用。这是我的机器上ProcMon生成的csv文件的快照。我只在文件中添加了一个过滤器,它是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的完整版本在上提供。csv文件中的每一行都对应于一个低级调用,另外还有一些由于路径上的严格筛选而被排除在外的绒毛。您的“TL;DR”问题很简短,切中要害,但我不确定回答这个问题是否能解决您的问题。汉斯·帕桑的答案可能更有用。不过,我会尽量提供一些资料
Windows有几个层,在本例中,两个有趣的层是Windows外壳API和系统服务API。您使用的Process.Start()
方式将在Windows Shell中调用。Windows外壳在Windows上提供了一个抽象,在Windows上有一个桌面(实际上是某个磁盘上的文件夹),文件被视为带有图标和动词的文档来操作这些文档。在本例中,您使用的是Open
动词
Windows Shell非常复杂,可以进行扩展,因此ShellExecuteEx
对特定路径和动词所做的操作很容易回答。这取决于本地计算机上注册的内容。但是,如果文件是PDF文件,动词是Open
,那么shell将运行与注册表中.PDF
扩展名关联的任何应用程序
在Windows 7中,您可以在控制面板程序默认程序中检查和修改文件关联。我怀疑如果与.PDF
扩展名关联的程序丢失,您可能会得到FileNotFoundException
,但我尚未验证
如果shell决定执行一个应用程序,它将在某个时候调用系统服务层并使用该函数创建一个新进程。对于PDF文件(取决于.PDF
的注册),将创建使用单个命令行参数执行Acrobat.exe
的进程(您指定的文件)
要解决此问题,您可以在com
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);