C ++程序需要文件关联

时间:2013-11-27 14:37:18

标签: c++ windows registry windows-installer file-association

我正在分发一个免费软件产品,该产品可以读取和写入具有唯一扩展名的文本文件。我希望双击这样的文件会自动启动应用程序。

在Windows 7 Professional上进行开发时,我设置了一个关联,双击打开我的文件,右键单击文件 - >打开方式...->选择默认程序...->浏览...后跟“始终使用所选程序打开此类文件”。好。它完成了它所需要的。我打算发送我的程序,并指示用户也这样做。

然而,当我移动二进制文件的位置时,我看到“Always use”现在变灰/不敏感,所以虽然我可以浏览到新的二进制文件但我无法将其设置为默认值。由于我认为我的用户也会遇到这个问题,我想看看我是否可以安装或运行程序来处理映射。

我查看了Windows Installer大约5分钟,然后才确定它比我需要的功能和复杂性要多得多(根据我的需要,除了这个文件映射之外,zip文件就足够了。)

所以我看了一下我的程序,在启动时,如果它已经没有那么设置映射本身。 (我知道如果我们讨论的是常见的文件类型,例如.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 Installer吗?或者有没有办法获得我自己的软件第一次启动时编辑注册表所需的权限?

注意我正在使用Windows 7 Professional上的Visual Studio 2008开发,虽然仍然是业余Windows程序员,但自从80年代以来我一直在使用C ++进行Unix / Linux ...

2 个答案:

答案 0 :(得分:5)

好的,我让它工作了,我会分享我学到的东西。

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 and   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行比开始更容易弄清楚如何配置安装程序。这是针对alpha版本的,我将观看此主题,以便为将来的版本提供更好的创意。

答案 1 :(得分:0)

注册表更改以及需要更高权限的所有操作都应在安装阶段完成,而不是在应用程序启动时完成。您可能想要使用installation软件。否则,您的软件将造成严重的安全漏洞。