如果我用ShellExecute
运行一个进程(或者在.net中用System.Diagnostics.Process.Start()
),要启动的进程的文件名不需要是完整路径。
如果我想启动记事本,我可以使用
Process.Start("notepad.exe");
而不是
Process.Start(@"c:\windows\system32\notepad.exe");
因为directory c:\windows\system32
是PATH环境变量的一部分。
我怎样才能检查一个文件是否存在于路径上而不执行进程和不解析路径变量?
System.IO.File.Exists("notepad.exe"); // returns false
(new System.IO.FileInfo("notepad.exe")).Exists; // returns false
但我需要这样的东西
System.IO.File.ExistsOnPath("notepad.exe"); // should return true
和/或
System.IO.File.GetFullPath("notepad.exe"); // (like unix which cmd) should return
// c:\windows\system32\notepad.exe
BCL中是否有预定义的类来执行此任务?
9条答案
按热度按时间kmpatx3s1#
我认为它没有内置的东西,但是你可以用System.IO.File.Exists做这样的事情:
x6yk4ghg2#
这是有风险的,它不仅仅是在PATH中搜索目录。试试这个:
可执行文件存储在我的机器上的c:\Program Files\Windows NT\Accessories中,该目录 * 不在 * 路径上。
HKCR\Applications和HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths键在查找可执行文件时也起作用。我相当肯定还有其他类似的地雷,例如,64位版本的Windows中的目录虚拟化可能会让你绊倒。
为了使它更可靠,我认为您需要pinvoke AssocQueryString()。不确定,从来没有必要。更好的方法当然是不必问这个问题。
qco9c6ql3#
好吧,我觉得更好的方法……
这将使用 where 命令,该命令至少在Windows 7/Server 2003上可用:
8zzbczxx4#
我尝试了Dunc的
where
进程,它工作,但它很慢,资源很重,而且有一个孤立进程的轻微危险。我喜欢尤金Mala关于
PathFindOnPath
的提示,所以我把它作为一个完整的答案来充实。这就是我使用的自定义内部工具。sqougxex5#
接受的答案是没有内置的东西,但这不是真的。有一个标准的WinAPI PathFindOnPath可以做到这一点,它是自Windows 2000以来可用的。
p4tfgftt6#
更短更直接,这正是海报想要的。
06odsfpq7#
我也在追求同样的事情,我认为我现在最好的选择是使用本机调用CreateProcess来创建一个进程挂起并观察成功;随后立即终止该过程。终止一个暂停的进程不应该导致任何资源流失[引文需要:)]
我可能无法计算出实际使用的路径,但对于ExistsOnPath()这样的简单需求,它应该可以--直到有更好的解决方案。
idfiyjo88#
我结合了@罗恩和@Hans Passant的答案,创建了一个类,通过调用
PathFindOnPath
来检查App Path
注册表项和PATH
中的文件路径。它还允许省略文件扩展名。在这种情况下,它会从PATHEXT
中探测几个可能的“可执行”文件扩展名。使用方法:
下面是代码:
nr7wwzry9#
为什么不尝试/ catch
Process.Start()
方法并处理catch中的任何问题?唯一的问题可能是,当找不到所需的可执行文件时,Process.Start()将返回一个相当不特定的
Win32Exception
。所以像catch (FileNotFoundException ex)
这样的东西是不可能的。但是你可以使用
Win32Exception.NativeErrorCode
属性来解决这个问题,以进行进一步的分析:有关
Win32Exception.NativeErrorCode
的列表,请参见https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/18d8fbe8-a967-4f1c-ae50-99ca8e491d2d?redirectedfrom=MSDN