【问题标题】:How to find an EXE's install location - the proper way?如何找到 EXE 的安装位置 - 正确的方法?
【发布时间】:2014-12-24 03:40:21
【问题描述】:

我正在用 C# 和 MATLAB 制作一个软件,它调用另一个软件 (CMG) 来进行一些处理。我的问题是我放入程序中的软件地址仅在我的个人计算机上正确,而不在客户的计算机上正确(我不知道他们计算机上 CMG 软件的路径是什么)。

如何提供一般形式的地址以使其在每台计算机上都可以使用?

以下是我从我的 MATLAB 软件中调用的路径:

C:\Program Files (x86)\CMG\STARS\2011.10\Win_x64\EXE\st201110.exe

如您所见,它位于驱动器 C 中,版本为 2011.10。因此,如果客户的版本是其他版本并且安装在其他驱动器上,则此路径毫无意义。

【问题讨论】:

  • 应该有办法从注册表中获取这些信息,但我不确定如何获取它们。
  • 您还可以显示uigetfile 对话框(或 C# 中的等效项)来提示用户自己选择“CMG”可执行文件。
  • 关于注册表的想法,这是特定于应用程序的,但您可以查看这个问题:stackoverflow.com/q/429738/97160

标签: c# windows matlab path pathname


【解决方案1】:

方法一

注册表项SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall 提供了大多数 应用程序的安装位置列表:

注意:它没有列出 PC 上的所有 EXE 应用程序,因为有些不需要安装。

在您的情况下,我很确定 CMG STARS 将被列出,您将能够通过遍历所有子键来搜索它,查看 DisplayName 值并获取 InstallLocation。

另请注意,此 Uninstall 注册表项存在于注册表中的 3 个位置:
1. SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall 在 CurrentUser
2. SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall 在 LocalMachine
3. SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall in LocalMachine

这是一个返回应用程序安装位置的类:

using Microsoft.Win32;

public static class InstalledApplications
{
    public static string GetApplictionInstallPath(string nameOfAppToFind)
    {
        string installedPath;
        string keyName;

        // search in: CurrentUser
        keyName = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
        installedPath = ExistsInSubKey(Registry.CurrentUser, keyName, "DisplayName", nameOfAppToFind);
        if (!string.IsNullOrEmpty(installedPath))
        {
            return installedPath;
        }

        // search in: LocalMachine_32
        keyName = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
        installedPath = ExistsInSubKey(Registry.LocalMachine, keyName, "DisplayName", nameOfAppToFind);
        if (!string.IsNullOrEmpty(installedPath))
        {
            return installedPath;
        }

        // search in: LocalMachine_64
        keyName = @"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall";
        installedPath = ExistsInSubKey(Registry.LocalMachine, keyName, "DisplayName", nameOfAppToFind);
        if (!string.IsNullOrEmpty(installedPath))
        {
            return installedPath;
        }

        return string.Empty;
    }

    private static string ExistsInSubKey(RegistryKey root, string subKeyName, string attributeName, string nameOfAppToFind)
    {
        RegistryKey subkey;
        string displayName;

        using (RegistryKey key = root.OpenSubKey(subKeyName))
        {
            if (key != null)
            {
                foreach (string kn in key.GetSubKeyNames())
                {
                    using (subkey = key.OpenSubKey(kn))
                    {
                        displayName = subkey.GetValue(attributeName) as string;
                        if (nameOfAppToFind.Equals(displayName, StringComparison.OrdinalIgnoreCase) == true)
                        {
                            return subkey.GetValue("InstallLocation") as string;
                        }
                    }
                }
            }
        }
        return string.Empty;
    }
}

这是你的称呼:

string installPath = InstalledApplications.GetApplictionInstallPath(nameOfAppToFind);

要获取 nameOfAppToFind,您需要查看注册表中的 DisplayName:

REF:我将上面的代码从here修改为返回安装路径。


方法二

您也可以使用系统管理 .Net DLL 来获取 InstallLocation,尽管它的速度会慢很多,并且会为您系统上的每个已安装产品创建“Windows Installer 重新配置产品”事件日志消息。

using System.Management;

ManagementObjectSearcher mos = new ManagementObjectSearcher("SELECT * FROM Win32_Product");
foreach (ManagementObject mo in mos.Get())
{
    Debug.Print(mo["Name"].ToString() + "," + mo["InstallLocation"].ToString() + Environment.NewLine);
}

获取 EXE 的名称

上述方法都不会告诉您可执行文件的名称,但是通过遍历安装路径中的所有文件并使用我讨论过的技术很容易解决here to look at file properties用正确的文件描述检测EXE,例如:

private string GetFileExeNameByFileDescription(string fileDescriptionToFind, string installPath)
{
    string exeName = string.Empty;
    foreach (string filePath in Directory.GetFiles(installPath, "*.exe"))
    {   
        string fileDescription = GetSpecificFileProperties(filePath, 34).Replace(Environment.NewLine, string.Empty);
        if (fileDescription == fileDescriptionToFind)
        {
            exeName = GetSpecificFileProperties(filePath, 0).Replace(Environment.NewLine, string.Empty);
            break;
        }
    }
    return exeName;
}


您使用的任何一种方法(1或2)我建议您保存exe名称的位置,以便您只执行一次此操作。在我看来,最好使用方法 1,因为它更快,并且不会创建所有“Windows Installer 重新配置产品”。事件日志。


使用安装程序的替代方法

如果您的应用程序正在安装,您可以在安装过程中找到 CMG STARS 的位置Using Windows Installer to Inventory Products and Patches

列举产品
使用MsiEnumProductsEx 函数枚举安装在 系统。此功能可以找到所有每台机器的安装和 每个用户安装的应用程序(托管和非托管) 当前用户和系统中的其他用户。使用 dwContext 参数指定要找到的安装上下文。你可以 指定可能的安装中的任何一种或任意组合 上下文。使用 szUserSid 参数指定用户上下文 找到应用程序。

在安装过程中,您会找到 CMG STARS 的 exe 路径并使用该值保存注册表项。

我讨论使用saving an EXE's install path in the registry for updating applications here 的这种方法。


提示

如 cmets 中所述,值得您在注册表中搜索 EXE 的名称 st201110.exe 并查看 CMG STAR 应用程序的作者是否已在注册表中提供此信息您可以直接访问的密钥。


B计划

如果所有其他方法都失败,则向用户显示 FileOpenDialog 并让他们手动指定 exe 的路径。


如果第 3 方应用程序被卸载或升级了怎么办?

我提到将安装路径和 exe 名称存储在注册表(或数据库、配置文件等)中,并且在对它进行任何外部调用之前,您应该始终检查 exe 文件是否存在,例如:

if (!File.Exists(installPath + exeName))
{
//Run through the process to establish where the 3rd party application is installed
}

【讨论】:

  • +1 这是一个彻底的答案!如果 OP 需要从 MATLAB 执行此检测,则有等效的函数可以查询注册表:mathworks.com/help/matlab/ref/winqueryreg.html
  • @JeremyThompson 方法 #1 发现应用程序已为我安装,但没有 InstallLocation 密钥可从中获取 exeDisplayIcon 键有 exe 路径,但我不知道这是否可靠使用?
  • 这个答案很大程度上取决于您要查找的软件 - 它不是一个适合所有解决方案的解决方案,这就是我包含 planB 方法的原因。如果可用的话,使用 DisplayIcon 应该没问题,而且开发人员很少在他们的安装程序中更改这类东西。有趣的是,您尝试查找的应用程序使用了 DisplayIcon,也许他们使用它来防止/允许人们更改应用程序图标。
  • 那么如何使用第一种方法来确定应用程序是否已安装并显示其位置?
  • @Burgo855 我编辑了答案以展示如何使用它。由于其已编辑,您可以更改您的投票。干杯
猜你喜欢
  • 2013-09-25
  • 1970-01-01
  • 2018-06-13
  • 2018-07-14
  • 2014-07-20
  • 2021-12-26
  • 1970-01-01
  • 2019-11-29
  • 2020-10-18
相关资源
最近更新 更多