2013-11-27 4 views
3

Я распространяю бесплатный продукт, который читает и записывает текстовые файлы с уникальным расширением. Я надеялся, что двойной щелчок на таком файле автоматически запустит приложение.Программе на C++ необходима ассоциация файлов

При разработке на Windows 7 Professional я настроил ассоциацию, чтобы открыть мои файлы при двойном щелчке, щелкнув правой кнопкой мыши файл-> Открыть с ...-> Выбрать программу по умолчанию ...-> Обзор. .. за которым следует «Всегда использовать выбранную программу для открытия этого типа файла». Хорошо. Он сделал то, что нужно. Я собирался отправить свою программу с инструкциями для пользователей делать то же самое.

Однако, когда я переместил местоположение двоичного файла, я вижу, что «Всегда использовать» теперь выделено серым цветом/нечувствительным, поэтому, когда я могу перейти к новому двоичному файлу, я не смог сделать его по умолчанию. Поскольку я думал, что у моих пользователей тоже будут проблемы с этим, я хотел бы посмотреть, смогу ли установка или запуск программы заботиться о сопоставлении.

Я посмотрел на Windows Installer, в течение примерно 5 минут, прежде чем определить, что было гораздо больше мощности и сложности, чем я нуждался (для моих потребностей, почтовый файл будет достаточно для этого файла отображения, за исключением.)

Так что я взял посмотрите, как моя программа при запуске настроила отображение, если оно уже не было. (Я знаю, что это было бы очень плохое поведение, если бы мы говорили об общем типе файлов, таких как .html или .jpg, но в этом случае его расширение .blahblah, которое, безусловно, никто не использует ни для чего.)

Основываясь на информации на http://www.cplusplus.com/forum/windows/26987/ и http://msdn.microsoft.com/en-us/library/cc144148(v=vs.85).aspx Мне удалось запустить мою программу при запуске, открыть HKEY_CLASSES_ROOT \ .blahblah и подтвердить (и при необходимости изменить) текст по умолчанию, чтобы быть точным описанием файла (заменив текст, который, возможно, был созданный по умолчанию, когда я провел ассоциацию вручную прошлым летом). Однако, когда дело дошло до создания команды HKEY_CLASSES_ROOT \ firm.app.1 \ shell \ open \, моя оболочка RegCreateKeyEx(), которая отлично работает, чтобы изменить значение \ .blahblah, теперь дает код возврата 5, по-видимому, отсутствие разрешения.

При дальнейших исследованиях кажется, что модель разрешений может привести к сбою всех таких запросов. Может ли кто-нибудь подтвердить или опровергнуть это? Если подтвердите, есть ли хорошая рекомендация, я должен изучить этот вопрос?

В противном случае, какие предложения? Должен ли я кусать пулю и изучать установщик Windows? Или есть способ получить разрешения, необходимые для редактирования реестра, когда мое собственное программное обеспечение запускается в первый раз?

Примечание Я разрабатываю с Visual Studio 2008 на Windows 7 Professional, и, хотя все еще любитель Windows, программист я делал C++, так как 80-х годов на Unix/Linux ...

+0

Что такое выполнение программы как root? Обычно установщики должны делать то же самое. Существуют также функции, позволяющие вашей программе запрашивать расширенное разрешение (вызывая появление этого желтого окна). – Paranaix

+0

Спасибо Паранаикс. Оказывается, что внесение изменений в HKEY_CURRENT_USER рекомендуется и не требует root. Лично, учитывая выбор между установкой не-доверенного программного обеспечения как root и запуском чего-то как обычного пользователя, я бы предпочел позже. –

ответ

3

ОК, я получил его, и я поделюсь тем, что узнал.

1) Определите ProgID. Он должен быть vender.app.versionnumber в соответствии с документами, но regedit показывает, что практически ни один поставщик не следует этому правилу. Я все же это сделал.

2) Большинство докторов MSFT на эту тему говорить о создании записей под HKEY_CLASSES_ROOT, но я нашел важную информацию о http://msdn.microsoft.com/en-us/library/cc144148(v=vs.85).aspx:

Важные соображения о типах файлов включают в себя: HKEY_CLASSES_ROOT поддерево вид формируется путем слияния HKEY_CURRENT_USER \ Software \ Classes и HKEY_LOCAL_MACHINE \ Software \ Classes В целом HKEY_CLASSES_ROOT - это , предназначенный для чтения, но не написанного. Для получения дополнительной информации см. Статью статьи HKEY_CLASSES_ROOT.

3) чтобы связь возникла без перезагрузки, вы должны вызвать SHChangeNotify(). (Это меня бросило, потому что даже когда у меня был правильный код, результаты не отображались правильно в проводнике.)

Вот код, в котором я закончил. Если я перейду с помощью REGEDIT и удалю все упоминания о .moselle (мое расширение) и MoselleIDE (мое приложение), тогда запустите мою программу один раз вручную, я получаю поведение от клика к открытому файлу, значок файла становится таким же, как и приложение, и т. д. Обратите внимание, что в коде используется функция ведения журнала, а также достаточно подробный отчет о том, какой тип успеха он имеет: 1) переменная уже правильная, 2) измененная переменная, 3) переменная не существует.

void RegSet(HKEY hkeyHive, const char* pszVar, const char* pszVa 

lue) { 

    HKEY hkey; 

    char szValueCurrent[1000]; 
    DWORD dwType; 
    DWORD dwSize = sizeof(szValueCurrent); 

    int iRC = RegGetValue(hkeyHive, pszVar, NULL, RRF_RT_ANY, &dwType, szValueCurrent, &dwSize); 

    bool bDidntExist = iRC == ERROR_FILE_NOT_FOUND; 

    if (iRC != ERROR_SUCCESS && !bDidntExist) 
     AKS(AKSFatal, "RegGetValue(%s): %s", pszVar, strerror(iRC)); 

    if (!bDidntExist) { 
     if (dwType != REG_SZ) 
      AKS(AKSFatal, "RegGetValue(%s) found type unhandled %d", pszVar, dwType); 

     if (strcmp(szValueCurrent, pszValue) == 0) { 
      AKS(AKSTrace, "RegSet(\"%s\" \"%s\"): already correct", pszVar, pszValue); 
      return; 
     } 
    } 

    DWORD dwDisposition; 
    iRC = RegCreateKeyEx(hkeyHive, pszVar, 0, 0, 0, KEY_ALL_ACCESS, NULL, &hkey, &dwDisposition); 
    if (iRC != ERROR_SUCCESS) 
     AKS(AKSFatal, "RegCreateKeyEx(%s): %s", pszVar, strerror(iRC)); 

    iRC = RegSetValueEx(hkey, "", 0, REG_SZ, (BYTE*) pszValue, strlen(pszValue) + 1); 
    if (iRC != ERROR_SUCCESS) 
     AKS(AKSFatal, "RegSetValueEx(%s): %s", pszVar, strerror(iRC)); 

    if (bDidntExist) 
     AKS(AKSTrace, "RegSet(%s): set to \"%s\"", pszVar, pszValue); 
    else 
     AKS(AKSTrace, "RegSet(%s): changed \"%s\" to \"%s\"", pszVar, szValueCurrent, pszValue); 

    RegCloseKey(hkey); 
} 



int SetUpRegistry() { 

    //app doesn't have permission for this when run as normal user, but may for Admin? Anyway, not needed. 
    //RegSet(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\MoselleIDE.exe", "C:\\Moselle\\bin\\MoselleIDE.exe"); 

    RegSet(HKEY_CURRENT_USER, "Software\\Classes\\.moselle", "Moselle.MoselleIDE.1"); 

    // Not needed. 
    RegSet(HKEY_CURRENT_USER, "Software\\Classes\\.moselle\\Content Type", "text/plain"); 
    RegSet(HKEY_CURRENT_USER, "Software\\Classes\\.moselle\\PerceivedType", "text"); 

    //Not needed, but may be be a way to have wordpad show up on the default list. 
    //RegSet(HKEY_CURRENT_USER, "Software\\Classes\\.moselle\\OpenWithProgIds\\Moselle.MoselleIDE.1", ""); 

    RegSet(HKEY_CURRENT_USER, "Software\\Classes\\Moselle.MoselleIDE.1", "Moselle IDE"); 

    RegSet(HKEY_CURRENT_USER, "Software\\Classes\\Moselle.MoselleIDE.1\\Shell\\Open\\Command", "C:\\Moselle\\bin\\MoselleIDE.exe %1"); 

    SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); 
    return 0; 
} 

Наконец, да, я знаю, что я должен выяснить инсталлятор, но я эксперт по C++, а не конфигурации и терминологии эксперт Windows, и его намного легче для меня, чтобы написать выше 50 строк, чем это чтобы даже начать выяснять, как настроить установщика. Это для альфа-релиза, и я буду смотреть эту тему для лучших идей для будущих выпусков.

+0

Надеюсь, вы не ожидаете, что ваша программа всегда будет работать с C: \\ Moselle \\ bin \\ MoselleIDE.exe. Вы бы сделали ваш метод SetUpRegistry более гибким, если обнаруживаете свой исполняемый путь во время выполнения и используете его для значения shell \ open \ command. Вы можете использовать функцию Win32 API GetModuleFileName, см. В MSDN: http://msdn.microsoft.com/en-us/library/windows/desktop/ms683197%28v=vs.85%29.aspx – regmagik

+0

Еще один комментарий о командной строке параметр% 1 передан вашему исполняемому файлу. Вы тестировали, что он работает, когда имя файла .moselle или любая родительская папка содержат пробелы? Например, 'C: \ Documents and Settings \ my.moselle' или' C: \ folder \ my sample.moselle'? Обходной путь для проблемы «пробелы в пути» заключается в использовании кавычек при прохождении параметра: myprogram.exe «% 1» – regmagik

+0

Оба отличных предложения, с которыми мы с Regmagik и сегодня включаем. –

0

изменения реестра и все действия, требующие более высоких разрешений, должны выполняться на этапе установки, а не при запуске приложения. Возможно, вы захотите использовать программное обеспечение installation. В противном случае ваше программное обеспечение создаст серьезное нарушение безопасности.

+0

Хорошо, да, но похоже, что бюджет времени для изучения Windows Installer превысит количество времени, которое я могу себе позволить. Однако, если вы или кто-нибудь быстро научились использовать какое-либо программное обеспечение для установки, я бы очень хотел его прочитать. –