Как найти каталог установки стороннего приложения, такого как Google Планета Земля, с помощью C#?

У меня есть следующий фрагмент кода, который запускает процесс Гугл Земля с использованием жестко заданного пути:

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 откуда-нибудь (скорее всего, из реестра).

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
4 362
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Из приведенного примера вы можете понять, что я на самом деле пытаюсь передать файл 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;
}

На моем компьютере путь, определенный в ключе InstallLocation, - C: \ Program Files \ Google \ Google Earth. Фактический исполняемый файл находится в C: \ Program Files \ Google \ Google Earth \ client \

Stealth Rabbi 10.08.2011 18:43

Вот версия 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);
            }
        }

Другие вопросы по теме