如何找到 EXE 的安装位置 - 正确的方法? [英] How to find an EXE's install location - the proper way?

查看:200
本文介绍了如何找到 EXE 的安装位置 - 正确的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我怎样才能提供地址的一般形式以使其在每台计算机上都能使用?

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

C:Program Files (x86)CMGSTARS2011.10Win_x64EXEst201110.exe

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

解决方案

方法一

注册表项SOFTWAREMicrosoftWindowsCurrentVersionUninstall 提供了大多数应用程序安装位置的列表:

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

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

另请注意,此卸载注册表项存在于注册表中的 3 个位置:
1. SOFTWAREMicrosoftWindowsCurrentVersionUninstall 里面 CurrentUser
2. SOFTWAREMicrosoftWindowsCurrentVersionUninstall in LocalMachine
3. SOFTWAREWow6432NodeMicrosoftWindowsCurrentVersionUninstall in LocalMachine

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

使用Microsoft.Win32;公共静态类 InstalledApplications{公共静态字符串 GetApplictionInstallPath(string nameOfAppToFind){字符串已安装路径;字符串键名;//搜索:当前用户keyName = @"SOFTWAREMicrosoftWindowsCurrentVersionUninstall";installedPath = ExistsInSubKey(Registry.CurrentUser, keyName, "DisplayName", nameOfAppToFind);if (!string.IsNullOrEmpty(installedPath)){返回安装路径;}//搜索:LocalMachine_32keyName = @"SOFTWAREMicrosoftWindowsCurrentVersionUninstall";installedPath = ExistsInSubKey(Registry.LocalMachine, keyName, "DisplayName", nameOfAppToFind);if (!string.IsNullOrEmpty(installedPath)){返回安装路径;}//搜索:LocalMachine_64keyName = @"SOFTWAREWow6432NodeMicrosoftWindowsCurrentVersionUninstall";installedPath = ExistsInSubKey(Registry.LocalMachine, keyName, "DisplayName", nameOfAppToFind);if (!string.IsNullOrEmpty(installedPath)){返回安装路径;}返回字符串.空;}私有静态字符串 ExistsInSubKey(RegistryKey root, string subKeyName, string attributeName, string nameOfAppToFind){RegistryKey 子项;字符串显示名称;使用 (RegistryKey key = root.OpenSubKey(subKeyName)){如果(键!= null){foreach (key.GetSubKeyNames() 中的字符串 kn){使用 (subkey = key.OpenSubKey(kn)){displayName = subkey.GetValue(attributeName) as string;if (nameOfAppToFind.Equals(displayName, StringComparison.OrdinalIgnoreCase) == true){return subkey.GetValue("InstallLocation") 作为字符串;}}}}}返回字符串.空;}}

这是你怎么称呼它的:

string installPath = InstalledApplications.GetApplictionInstallPath(nameOfAppToFind);

要获得 nameOfAppToFind,您需要在注册表中查看 DisplayName:

REF: 我从 :

<块引用>

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

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

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

<小时>

提示

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

<小时>

B 计划

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

<小时>

如果第三方应用被卸载或升级怎么办?

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

if (!File.Exists(installPath + exeName)){//运行该过程以确定安装第3方应用程序的位置}

I am making a software in C# and MATLAB that calls another software (CMG) to do some processing. My problem is that the address of the software I have put in my program is only correct on my personal computer and not on the customers' computers (I don't know what would be the path to CMG software on their computer).

How can I provide a general form of the address in order to make it work on every computer?

The following is the path I call from my MATLAB software:

C:Program Files (x86)CMGSTARS2011.10Win_x64EXEst201110.exe

As you see it is in drive C and the version is 2011.10. So if customer's version is something else and it is installed on other drives, this path makes no sense.

解决方案

Method 1

The registry keys SOFTWAREMicrosoftWindowsCurrentVersionUninstall provides a list of where most applications are installed:

Note: It doesn't list all EXE applications on the PC as some dont require installation.

In your case I am pretty sure that CMG STARS will be listed and you will be able to search for it by iterating over all subkeys looking at the DisplayName value and fetching the InstallLocation.

Also note that this Uninstall registry key exists in 3 places in the registry:
1. SOFTWAREMicrosoftWindowsCurrentVersionUninstall inside CurrentUser
2. SOFTWAREMicrosoftWindowsCurrentVersionUninstall inside LocalMachine
3. SOFTWAREWow6432NodeMicrosoftWindowsCurrentVersionUninstall in LocalMachine

Here is an class that returns the installed location of an application:

using Microsoft.Win32;

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

        // search in: CurrentUser
        keyName = @"SOFTWAREMicrosoftWindowsCurrentVersionUninstall";
        installedPath = ExistsInSubKey(Registry.CurrentUser, keyName, "DisplayName", nameOfAppToFind);
        if (!string.IsNullOrEmpty(installedPath))
        {
            return installedPath;
        }

        // search in: LocalMachine_32
        keyName = @"SOFTWAREMicrosoftWindowsCurrentVersionUninstall";
        installedPath = ExistsInSubKey(Registry.LocalMachine, keyName, "DisplayName", nameOfAppToFind);
        if (!string.IsNullOrEmpty(installedPath))
        {
            return installedPath;
        }

        // search in: LocalMachine_64
        keyName = @"SOFTWAREWow6432NodeMicrosoftWindowsCurrentVersionUninstall";
        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;
    }
}

Here is how you call it:

string installPath = InstalledApplications.GetApplictionInstallPath(nameOfAppToFind);

To get the nameOfAppToFind you'll need to look in the registry at the DisplayName:

REF: I modified the above code from here to return the install path.


Method 2

You can also use the System Management .Net DLL to get the InstallLocation although it is heaps slower and creates "Windows Installer reconfigured the product" event log messages for every installed product on your system.

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);
}


Getting the EXE's name

Neither of the above methods tell you the name of the executable, however it is quite easy to work out by iterating over all the files in the install path and using a technique I discuss here to look at file properties to detect the EXE with the correct File Description, eg:

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;
}


Either method (1 or 2) you use I recommend that you save the location of exe name so you only do this operation once. In my opinion its better to use Method 1 as its faster and doesn't create all the "Windows Installer reconfigured the product." event logs.


Alternate Method using an Installer

If your application is being installed you could find out where CMG STARS is located during installation Using Windows Installer to Inventory Products and Patches:

Enumerating Products
Use the MsiEnumProductsEx function to enumerate Windows Installer applications that are installed in the system. This function can find all the per-machine installations and per-user installations of applications (managed and unmanaged) for the current user and other users in the system. Use the dwContext parameter to specify the installation context to be found. You can specify any one or any combination of the possible installation contexts. Use the szUserSid parameter to specify the user context of applications to be found.

During installation you would find the exe path to CMG STARS and save a registry key with the value.

I discuss using this approach of saving an EXE's install path in the registry for updating applications here.


Tip

As mentioned in the comments, it is worthwhile you do a search in the registry for the EXE's name st201110.exe and see if the authors of the CMG STAR application already provide this information in a registry key you can access directly.


Plan B

If all else fails present the user with a FileOpenDialog and get them to specify the exe's path manually.


What if the 3rd party application is uninstalled or upgraded?

I mentioned to store the install path and exe name in the registry (or database, config file, etc) and you should always check the exe file exists before making any external calls to it, eg:

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

这篇关于如何找到 EXE 的安装位置 - 正确的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆