2013-11-27 37 views
3

我正在发布一个读写文本文件的免费软件产品,它具有唯一的扩展名。我希望双击这样的文件会自动启动应用程序。C++程序需要一个文件关联

虽然在Windows 7专业发展,我成立了一个协会在打开我的文件双击,右键点击文件 - >打开方式...->选择默认程序...->浏览。 ..随后“始终使用选定的程序来打开这种类型的文件。”好。它只是做了它需要的。我准备发布我的程序,指导用户做同样的事情。

然而,当我移动的二进制文件的位置,我看到了“始终使用”现在变灰/不敏感,所以虽然我可以浏览到新的二进制我不能让它违约。因为我认为我的用户也会遇到麻烦,所以我想看看是否可以安装或运行程序来处理映射。

我看着Windows安装约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 \ command时,我的RegCreateKeyEx()包装器可以正常工作以更改\ .blahblah的值,现在给出返回代码5,显然是缺少权限。

在进一步的研究似乎权限模型可能会导致所有这些请求失败。任何人都可以确认或否认这一点?如果确认,是否有一个很好的参考,我应该研究这个问题?

否则,有什么建议?我应该咬紧牙关,学习Windows Installer吗?或者当我自己的软件第一次启动时,是否有办法获得我需要编辑注册表的权限?

注意我与Visual Studio 2008的Windows 7专业发展,虽然仍然是一个业余的Windows程序员,我一直在做C++,因为在Unix/Linux上世纪80年代...

+0

如何以root身份执行程序?安装人员通常必须这样做。还有一些功能允许程序请求扩展权限(使黄色窗口弹出)。 – Paranaix

+0

谢谢Paranaix。事实证明,建议在HKEY_CURRENT_USER中进行更改,并且不需要root。就个人而言,如果选择安装不是非常值得信赖的软件作为root用户,并以普通用户身份运行某些软件,我宁愿选择后者。 –

回答

3

OK,我得到了它的工作,我会分享我的教训。

1)决定一个ProgID。根据文档,它应该是vender.app.versionnumber,但注册表显示实际上没有任何供应商遵循该规则。但我做到了。

2)大多数关于这个主题谈创建下HKEY_CLASSES_ROOT项MSFT文档的,但我发现重要的信息上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条线甚至开始了解如何配置安装程序。这是一个alpha版本,我会观看这个话题,以获得更好的未来版本的想法。

+0

我希望你不要指望你的程序总是从C:\\ Moselle \\ bin \\ MoselleIDE.exe运行。如果您在运行时检测到可执行文件路径并将其用于shell \ open \ command值,则会使您的SetUpRegistry方法更加灵活。您可以使用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的时间预算会超出我能负担得起的时间。但是,如果你或任何人有一个快速的方法来使用任何安装软件来做到这一点,我会急于阅读它。 –