У меня есть следующий фрагмент кода, который запускает процесс Гугл Земля с использованием жестко заданного пути:
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();
Я хочу программно получить место установки googleearth.exe откуда-нибудь (скорее всего, из реестра).





Из приведенного примера вы можете понять, что я на самом деле пытаюсь передать файл KML в Google Планета Земля. Из-за этого самый простой способ решить эту проблему - полагаться на ассоциацию файлов KML с Google Планета Земля и использовать следующее в качестве замены всего примера:
Process.Start(kmlPath);
Это было обнаружено при просмотре ответов на вопрос это.
Очевидно, что если вы открываете определенный файл, связанный с программой, то запускать его через файл предпочтительнее (например, у пользователя может быть программа, связанная с типом файла, который он предпочитает использовать).
Вот метод, который я использовал в прошлом для запуска приложения, связанного с определенным типом файла, но без фактического открытия файла. Может быть, есть лучший способ сделать это.
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;
}
Однако иногда бывают случаи, когда вы хотите запустить конкретную программу, не открывая файл. Обычно (надеюсь) программа имеет запись в реестре с указанием места установки. Вот пример того, как таким образом запустить 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;
}
Вот версия C++, которую мне просто нужно было написать. Взято непосредственно из версии C# ICR.
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();
}
}
Это также сработает: (код 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);
}
}
На моем компьютере путь, определенный в ключе InstallLocation, - C: \ Program Files \ Google \ Google Earth. Фактический исполняемый файл находится в C: \ Program Files \ Google \ Google Earth \ client \