Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用MFC以编程方式更改文件扩展名关联?_C++_Winapi_Mfc_Inno Setup_File Association - Fatal编程技术网

C++ 使用MFC以编程方式更改文件扩展名关联?

C++ 使用MFC以编程方式更改文件扩展名关联?,c++,winapi,mfc,inno-setup,file-association,C++,Winapi,Mfc,Inno Setup,File Association,我可以在InitInstance中使用此代码来确认哪个可执行文件与给定扩展关联: TCHAR szRegisteredEXE[_MAX_PATH]; DWORD dwBufferLen = _MAX_PATH; HRESULT hRes = AssocQueryString(ASSOCF_NONE, ASSOCSTR_EXECUTABLE, _T("MeetSchedAssist.MWB"), NULL, szRegisteredEXE, &

我可以在
InitInstance
中使用此代码来确认哪个可执行文件与给定扩展关联:

TCHAR szRegisteredEXE[_MAX_PATH];
DWORD dwBufferLen = _MAX_PATH;

HRESULT  hRes = AssocQueryString(ASSOCF_NONE, ASSOCSTR_EXECUTABLE, 
                    _T("MeetSchedAssist.MWB"), NULL, szRegisteredEXE, &dwBufferLen);
if (hRes == S_OK)
{
    // TODO
}
它很好用

我的软件安装32位版本和64位版本的可执行文件。因此,如果注册的exe不是活动的exe,我希望代码能够提示更新关联


我知道如何获取我的活动exe路径,以及如何确认它是否匹配
szRegisteredEXE
,但是如何更新文件关联(假设用户对关联提示说是)?

第一步是创建一个Inno安装程序,该安装程序将为我们管理注册表的调整:

; SignTool parameters
#define SignedDesc "$qMeeting Schedule Assistant File Associations Tool$q"
#define SignedPfx "$q~~~~~$q"
#define SignedTimeStamp "$qhttp://timestamp.verisign.com/scripts/timestamp.dll$q"
#define SignedPw "$q~~~~~$q"

#define AppURL "https://www.publictalksoftware.co.uk"
#define AppPublisher "~~~~~"

#define AppVerText() \
   ParseVersion('..\Meeting Schedule Assistant\Release\Meeting Schedule Assistant.exe', \
       Local[0], Local[1], Local[2], Local[3]), \
   Str(Local[0]) + "." + Str(Local[1]) + "." + Str(Local[2])

[Setup]
DisableReadyPage=True
DisableReadyMemo=True
DisableFinishedPage=True
UsePreviousSetupType=False
UsePreviousTasks=False
UsePreviousLanguage=False
FlatComponentsList=False
AlwaysShowComponentsList=False
ShowComponentSizes=False
AppName=Meeting Schedule Assistant File Associations Tool
AppVersion={#AppVerText}
CreateAppDir=False
Uninstallable=no
OutputBaseFilename=MSATweakFileAssociations
SignTool=SignTool /d {#SignedDesc} /du $q{#AppURL}$q /f {#SignedPfx} /p {#SignedPw} /t {#SignedTimeStamp} /v $f
AppId={{~~~~~}

[registry]
Root: HKCR; SubKey: "MeetSchedAssist.MWB\Shell\Open\Command"; ValueType: string; ValueData: """{param:ExePath}"" ""%1""";
Root: HKCR; SubKey: "MeetSchedAssist.SRR\Shell\Open\Command"; ValueType: string; ValueData: """{param:ExePath}"" ""%1""";
然后,在MFC中,我们运行我们的工具,如下所示:

void COptionsDlg::OnBnClickedMfcbuttonFileAssociations()
{
    // Try to run the help installer
    CString strSetupExe = _T("~~~~~.exe");
    CString strProgramFolder = theApp.GetProgramPath();
    CString strParams = _T("");

    strParams.Format(_T("/SP- /VERYSILENT /ExePath=\"%s\""), (LPCTSTR)theApp.GetProgramEXE());
    if (!theApp.ExecuteProgram(strProgramFolder + strSetupExe, strParams))
    {
        // Problem running the installer
        AfxMessageBox(_T("Unable to change the file associations"), MB_OK | MB_ICONERROR);
        return;
    }
}

BOOL CMeetingScheduleAssistantApp::ExecuteProgram(CString strProgram, CString strArguments)
{
    SHELLEXECUTEINFO    se = { 0 };
    MSG                 sMessage;
    DWORD               dwResult;

    theApp.SetProgramExecuting(true);

    se.cbSize = sizeof(se);
    se.lpFile = strProgram;
    se.lpParameters = strArguments;
    se.nShow = SW_SHOWDEFAULT;
    se.fMask = SEE_MASK_NOCLOSEPROCESS;
    ShellExecuteEx(&se);

    if (se.hProcess != nullptr)
    {
        do
        {
            dwResult = ::MsgWaitForMultipleObjects(1, &(se.hProcess), FALSE,
                INFINITE, QS_ALLINPUT);
            if (dwResult != WAIT_OBJECT_0)
            {
                while (PeekMessage(&sMessage, nullptr, NULL, NULL, PM_REMOVE))
                {
                    TranslateMessage(&sMessage);
                    DispatchMessage(&sMessage);
                }
            }
        } while ((dwResult != WAIT_OBJECT_0) && (dwResult != WAIT_FAILED));

        CloseHandle(se.hProcess);
    }

    theApp.SetProgramExecuting(false);

    if ((DWORD_PTR)(se.hInstApp) < 33)
    {
        // Throw error
        AfxThrowUserException();
        return FALSE;
    }

    SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);

    return TRUE;
}
void COptionsDlg::onbnClickedMFButtonFileAssociations()
{
//尝试运行帮助安装程序
CString strestupexe=\u T(“~~~~~~.exe”);
CString strProgramFolder=app.GetProgramPath();
CString strParams=\u T(“”);
格式(\u T(“/SP-/VERYSILENT/ExePath=\%s\”,(LPCTSTR)theApp.GetProgramEXE());
如果(!theApp.ExecuteProgram(strProgramFolder+strSetupExe,strParams))
{
//运行安装程序时出现问题
AfxMessageBox(_T(“无法更改文件关联”)、MB_OK | MB_icon);
返回;
}
}
BOOL CMeetingScheduleAssistantApp::ExecuteProgram(CString strProgram,CString strArguments)
{
SHELLEXECUTEINFO se={0};
味精涂片;
德沃德结果;
theApp.SetProgramExecuting(真);
se.cbSize=sizeof(se);
se.lpFile=strProgram;
se.lpParameters=strArguments;
se.nShow=SW_SHOWDEFAULT;
se.fMask=参见屏蔽过程;
ShellExecuteEx&se;
if(se.hProcess!=nullptr)
{
做
{
dwResult=::MsgWaitForMultipleObjects(1,&(se.hProcess),FALSE,
无限,QS_ALLINPUT);
if(dwResult!=等待对象0)
{
while(peek消息(&sMessage,nullptr,NULL,NULL,PM_REMOVE))
{
翻译信息(&sMessage);
DispatchMessage(&sMessage);
}
}
}而((dwResult!=WAIT_OBJECT_0)&&(dwResult!=WAIT_FAILED));
CloseHandle(se.hProcess);
}
theApp.SetProgramExecuting(假);
如果((德沃德·辛斯塔普东南部)<33)
{
//抛出错误
AfxThrowUserException();
返回FALSE;
}
SHChangeNotify(SHCNE_assocchange,SHCNF_IDLIST,NULL,NULL);
返回TRUE;
}

瞧!它会更新注册表

这很复杂,但可以做到。您需要在
HKEY\U CLASSES\U ROOT
中写入/替换注册表项,但仍有许多注册表项需要修改和链接。如果您安装了处理MWB扩展的程序,请查看
HKEY_CLASSES_ROOT\.MWB
HKEY_CLASSES_ROOT\MyDescription
键(其中
MyDescription
在第一个键中给出)。您还需要以提升的权限运行,否则我认为HKCR键将被虚拟化,因此,如果您对registry access API调用感到满意(就像我想象的那样),您可以深入并尝试!我认为在这个阶段尝试发布代码回答有点太多了,但是请随时回来询问您是否遇到问题。我很乐意(尝试)提供帮助。我认为可执行文件必须是“以管理员身份运行”(在清单文件中设置该要求),然后每次启动时都会(恼人地)不断请求管理员密码。但我不是100%确定-它们可能是启动后提升的一种方式(尽管仍然需要管理员密码提示-否则这将是一个简单的O/S攻击)。您可以构建一个从程序调用的“假”MSI安装程序,设置所需的文件关联。对于每个用户设置,请使用
HKEY\u CURRENT\u user\Software\Classes
。你不需要提升来完成它。@DanielSęk我的软件不是按用户设计的。但这一点值得注意。