11

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

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

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

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

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

4

1 回答 1

23

方法一

注册表项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 在 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:我从这里修改了上面的代码以返回安装路径。


方法二

您还可以使用系统管理 .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 的名称

上述两种方法都不会告诉您可执行文件的名称,但是通过遍历安装路径中的所有文件并使用我在此处讨论的技术来查看文件属性以检测正确的 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函数枚举安装在系统中的 Windows Installer 应用程序。此功能可以查找当前用户和系统中其他用户的所有每台机器安装和每用户安装的应用程序(托管和非托管)。使用 dwContext 参数指定要查找的安装上下文。您可以指定可能的安装上下文中的任何一个或任意组合。使用 szUserSid 参数指定要查找的应用程序的用户上下文。

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

我在这里讨论使用这种在注册表中保存 EXE 的安装路径以更新应用程序的方法


小费

正如评论中提到的,值得您在注册表中搜索 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
}
于 2014-11-01T06:20:25.277 回答