我正在用C#和MATLAB制作一个软件,调用另一个软件(CMG)进行一些处理。我的问题是,我在我的程序中放置的软件的地址只能在我的个人计算机上正确,而不是客户的地址。计算机(我不知道计算机上CMG软件的路径是什么)。
如何提供地址的一般形式,以使其适用于每台计算机?
以下是我从MATLAB软件调用的路径:
C:\Program Files (x86)\CMG\STARS\2011.10\Win_x64\EXE\st201110.exe
如您所见,它位于驱动器C中,版本为2011.10。因此,如果客户的版本是其他版本并且它安装在其他驱动器上,则此路径没有意义。
答案 0 :(得分:19)
注册表项 SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall 提供了大多数应用程序的安装位置列表:
注意:它没有列出PC上的所有EXE应用程序,因为有些不需要安装。
在您的情况下,我非常确定会列出CMG STARS,您可以通过遍历查看 DisplayName 值并获取 InstallLocation <的所有子项来搜索它。 /强>
另请注意,此Uninstall注册表项存在于注册表中的3个位置:
1.在CurrentUser中使用SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall
2.软件\ Microsoft \ Windows \ CurrentVersion \在LocalMachine中卸载
3. LocalWachine中的SOFTWARE \ Wow6432Node \ Microsoft \ Windows \ CurrentVersion \ Uninstall
这是一个返回应用程序安装位置的类:
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中查看注册表:
参考:我从here修改了上述代码以返回安装路径。
您也可以使用系统管理.Net DLL获取 InstallLocation ,尽管速度较慢并且创建了&#34; Windows Installer重新配置了产品&#34;系统上每个已安装产品的事件日志消息。
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);
}
上述两种方法都没有告诉您可执行文件的名称,但通过迭代安装路径中的所有文件并使用我讨论的技术 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,因为它更快,并且不会创建所有&#34; Windows Installer重新配置产品。&#34;事件日志。
如果您的应用程序正在安装,您可以在安装过程中找到CMG STARS所在的位置Using Windows Installer to Inventory Products and Patches:
枚举产品
使用MsiEnumProductsEx功能枚举安装在中的Windows Installer应用程序 系统。此功能可以找到所有每台机器的安装和 每个用户安装的应用程序(托管和非托管) 当前用户和系统中的其他用户。使用dwContext 参数,用于指定要查找的安装上下文。您可以 指定可能的安装中的任何一个或任何组合 上下文。使用szUserSid参数指定用户上下文 应用程序。
在安装过程中,您将找到CMG STARS的exe路径,并使用值保存注册表项。
我讨论使用saving an EXE's install path in the registry for updating applications here的这种方法。
如评论中所述,您可以在注册表中搜索EXE的名称 st201110.exe ,看看CMG STAR应用程序的作者是否已提供此功能您可以直接访问的注册表项中的信息。
如果所有其他方法都失败,则会向用户提供FileOpenDialog并让他们手动指定exe的路径。
我提到将安装路径和exe名称存储在注册表(或数据库,配置文件等)中,在进行任何外部调用之前,应始终检查exe文件是否存在,例如:
if (!File.Exists(installPath + exeName))
{
//Run through the process to establish where the 3rd party application is installed
}