获取未运行的应用程序的完整路径的最佳方法是什么?

时间:2018-11-13 07:33:55

标签: c#

我正在尝试使用Path.GetFullPath()获取应用程序“ WinMergeU.exe”的路径,但是此代码的返回值是我的应用程序的文件夹。

当使用C:返回值为d时,如何在Path.GetFullPath()驱动器中获取应用程序的完整路径。

3 个答案:

答案 0 :(得分:3)

您必须搜索以查找文件,例如

 using system.Linq;

 ...

 // Either full path of "WinMergeU.exe" file or null (if not found) 
 string result = Directory
   .EnumerateFiles(@"c:\", "WinMergeU.exe", SearchOption.AllDirectories)
   .FirstOrDefault();

编辑:如果应用程序位于C:\Program Files中(请参见注释),我们可以限制扫描:

  string result = Directory
    .EnumerateFiles(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles),
                    "WinMergeU.exe",
                    SearchOption.AllDirectories) 
    .FirstOrDefault();

或者(如果我们非常确定在c:\Program Files\WinMerge路径中),我们可以测试文件是否退出:

  string result = Path.Combine(
     Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles),
    "WinMerge",
    "WinMergeU.exe");

  if (File.Exists(result)) {
    // we have the file
  }

答案 1 :(得分:2)

我安装了它,因为它看起来很方便,并且搜索了注册表。

string key = @"HKEY_LOCAL_MACHINE\SOFTWARE\Classes\WinMerge.Project.File\shell\open\command";
string path = Microsoft.Win32.Registry.GetValue(key, "", -1);

...似乎包含您需要的值。就我而言:

"C:\Program Files (x86)\WinMerge\WinMergeU.exe" "%1"

如果找不到密钥,该方法将返回-1。

答案 2 :(得分:0)

WinMerge不允许更改其安装文件夹AFAIK,因此搜索整个驱动​​器C实在是过大。

这足够了:

static string GetWinMergeFullPath()
{
    const string executableName = "WinMergeU.exe";
    const string installationFolder = "WinMerge";
    var locations = new Environment.SpecialFolder[] 
    {
        Environment.SpecialFolder.ProgramFiles,
        Environment.SpecialFolder.ProgramFilesX86
    };

    string fullPath = locations
        .Select(l => Path.Combine(Environment.GetFolderPath(l), installationFolder, executableName))
        .Where(File.Exists)
        .FirstOrDefault();
    return fullPath ?? throw new FileNotFoundException(executableName);
}

编辑
正如上面所评论的那样,这还不够:)。以下版本使用两个注册表位置,其中应包含该路径。一个是安装程序提供的“应用程序路径”,第二个是“卸载”。尽管我相信“应用程序路径”应该足够了,但我仍然提供了第二个功能来确保鲁棒性。请注意,即使在安装程序中未选中外壳集成,它也能正常工作!涵盖了32位和64位安装。

static string GetWinMergeFullPathFromRegistryEx()
{
    const string executableName = "WinMergeU.exe";
    const string appPathKeyName = @"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\";
    const string uninstallKeyName = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\WinMerge_is1";
    const string installLocationName = "InstallLocation";

    var locations = new List<(string path, string value, bool withFilename)>
    {
        ($"{appPathKeyName}{executableName}", null, true),
        (uninstallKeyName, installLocationName, false),
    };

    List<RegistryView> views = Environment.Is64BitOperatingSystem ?
        new List<RegistryView>() { RegistryView.Registry32, RegistryView.Registry64 } :
        new List<RegistryView>() { RegistryView.Default };

    foreach (var view in views)
    {
        using (RegistryKey localMachine = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, view))
        foreach (var (path, value, withFilename) in locations)
        {
            using (RegistryKey key = localMachine.OpenSubKey(path, false))
            {
                var fullpathValue = key?.GetValue(value);
                if (fullpathValue != null)
                {
                    string fullpath = (string)fullpathValue;
                    if (!withFilename)
                        fullpath = Path.Combine(fullpath, executableName);
                    if (File.Exists(fullpath))
                        return fullpath;
                }
            }
        }
    }

    throw new FileNotFoundException(executableName);
}

当然,我的假设是实际上已安装WinMerge。如果您应该支持手动部署WinMerge的情况,那么仍然可以使用完整扫描选项作为后备。