[英]How to find the installation directory of a third-party application, such as Google Earth, using C#?
I have the following code fragment that starts a Google Earth process using a hardcoded path: 我有以下代码片段,它使用硬编码路径启动Google Earth进程:
var process =
new Process
{
StartInfo =
{
//TODO: Get location of google earth executable from registry
FileName = @"C:\Program Files\Google\Google Earth\googleearth.exe",
Arguments = "\"" + kmlPath + "\""
}
};
process.Start();
I want to programmatically fetch the installation location of googleearth.exe from somewhere (most likely the registry). 我想以编程方式从某个地方(很可能是注册表)获取googleearth.exe的安装位置。
From the example given you can gauge that I'm actually trying to pass a KML file to Google Earth. 从给出的示例中,您可以判断我实际上是在尝试将KML文件传递给Google地球。 Because of this, the simplest way of resolving this problem is relying on the file association of KML with Google Earth and using the following as a replacement for the entire example:
因此,解决此问题的最简单方法是依靠KML与Google Earth的文件关联,并使用以下内容替代整个示例:
Process.Start(kmlPath);
This was found by reviewing the answers to this question. 通过回顾这个问题的答案找到了这个 。
Obviously if you're opening a specific file associated with the program then launching it via the file is preferable (for instance, the user might have a program associated with the file type they prefer to use). 显然,如果您打开与该程序关联的特定文件,则最好通过该文件启动它(例如,用户可能有一个与他们喜欢使用的文件类型相关联的程序)。
Here is a method I've used in the past to launch an application associated with a particular file type, but without actually opening a file. 这是我过去用来启动与特定文件类型相关联的应用程序但不实际打开文件的方法。 There may be a better way to do it.
可能有更好的方法来做到这一点。
static Regex pathArgumentsRegex = new Regex(@"(%\d+)|(""%\d+"")", RegexOptions.ExplicitCapture);
static string GetPathAssociatedWithFileExtension(string extension)
{
RegistryKey extensionKey = Registry.ClassesRoot.OpenSubKey(extension);
if (extensionKey != null)
{
object applicationName = extensionKey.GetValue(string.Empty);
if (applicationName != null)
{
RegistryKey commandKey = Registry.ClassesRoot.OpenSubKey(applicationName.ToString() + @"\shell\open\command");
if (commandKey != null)
{
object command = commandKey.GetValue(string.Empty);
if (command != null)
{
return pathArgumentsRegex.Replace(command.ToString(), "");
}
}
}
}
return null;
}
Sometimes though there are cases when you want to launch a specific program without opening a file. 有时虽然有时您想在不打开文件的情况下启动特定程序。 Usually (hopefully) the program has a registry entry with the install location.
通常(希望)程序有一个带有安装位置的注册表项。 Here is an example of how to launch Google Earth in such a manner.
以下是如何以这种方式启动Google地球的示例。
private static string GetGoogleEarthExePath()
{
RegistryKey googleEarthRK = Registry.CurrentUser.OpenSubKey(@"Software\Google\Google Earth Plus\");
if (googleEarthRK != null)
{
object rootDir = googleEarthRK.GetValue("InstallLocation");
if (rootDir != null)
{
return Path.Combine(rootDir.ToString(), "googleearth.exe");
}
}
return null;
}
This would also work: (C# code) 这也可以:(C#代码)
Type type = Type.GetTypeFromProgID("WindowsInstaller.Installer");
Installer msi = (Installer)Activator.CreateInstance(type);
foreach (string productcode in msi.Products)
{
string productname = msi.get_ProductInfo(productcode, "InstalledProductName");
if (productname.Contains("Google Earth"))
{
string installdir = msi.get_ProductInfo(productcode, "InstallLocation");
Console.WriteLine("{0}: {1} @({2})", productcode, productname, installdir);
}
}
Here's a C++ version I just had to write. 这是我刚刚编写的C ++版本。 Taken directly from ICR's C# version.
直接取自ICR的C#版本。
void PrintString(CString string)
{
std::wcout << static_cast<LPCTSTR>(string) << endl;
}
CString GetClassesRootKeyValue(const wchar_t * keyName)
{
HKEY hkey;
TCHAR keyNameCopy[256] = {0};
_tcscpy_s(keyNameCopy, 256, keyName);
BOOL bResult = SUCCEEDED(::RegOpenKey(HKEY_CLASSES_ROOT, keyNameCopy, &hkey));
CString hkeyValue = CString("");
if (bResult) {
TCHAR temporaryValueBuffer[256];
DWORD bufferSize = sizeof (temporaryValueBuffer);
DWORD type;
bResult = SUCCEEDED(RegQueryValueEx(hkey, _T(""), NULL, &type, (BYTE*)temporaryValueBuffer, &bufferSize)) && (bufferSize > 1);
if (bResult) {
hkeyValue = CString(temporaryValueBuffer);
}
RegCloseKey(hkey);
return hkeyValue;
}
return hkeyValue;
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
_tprintf(_T("Fatal Error: MFC initialization failed\n"));
nRetCode = 1;
}
else
{
CString dwgAppName = GetClassesRootKeyValue(_T(".dwg"));
PrintString(dwgAppName);
dwgAppName.Append(_T("\\shell\\open\\command"));
PrintString(dwgAppName);
CString trueViewOpenCommand = GetClassesRootKeyValue(static_cast<LPCTSTR>(dwgAppName));
PrintString(trueViewOpenCommand);
// Shell open command usually ends with a "%1" for commandline params. We don't want that,
// so strip it off.
int firstParameterIndex = trueViewOpenCommand.Find(_T("%"));
PrintString(trueViewOpenCommand.Left(firstParameterIndex).TrimRight('"').TrimRight(' '));
cout << "\n\nPress <enter> to exit...";
getchar();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.