【问题标题】:Shell Execute From Explorer从资源管理器执行 Shell
【发布时间】:2021-11-21 20:49:40
【问题描述】:

尝试遵循此示例: https://devblogs.microsoft.com/oldnewthing/20040520-00/?p=39243

void ShellExecuteFromExplorer(PCWSTR pszFile,    PCWSTR pszParameters = nullptr,    PCWSTR pszDirectory  = nullptr,    PCWSTR pszOperation  = nullptr,    int nShowCmd         = SW_SHOWNORMAL)
{
    CComPtr<IShellFolderViewDual> spFolderView;
    GetDesktopAutomationObject(IID_PPV_ARGS(&spFolderView));
    CComPtr<IDispatch> spdispShell;
    spFolderView->get_Application(&spdispShell);
    CComQIPtr<IShellDispatch2>(spdispShell)
       ->ShellExecute(CComBSTR(pszFile),
                      CComVariant(pszParameters ? pszParameters : L""),
                      CComVariant(pszDirectory ? pszDirectory : L""),
                      CComVariant(pszOperation ? pszOperation : L""),
                      CComVariant(nShowCmd));
}

在这种情况下,我如何从ShellExecute 启动的进程中检索pid

【问题讨论】:

标签: c++ windows winapi


【解决方案1】:

在这种情况下,我如何从ShellExecute 启动的进程中检索pid

你不能。就像::ShellExecute() 一样,IShellDispatch2::ShellExecute() 根本不提供有关新进程的任何信息。

【讨论】:

    【解决方案2】:

    不需要使用这种方式来创建未提升的进程。例如,我们可以在PROC_THREAD_ATTRIBUTE_PARENT_PROCESS 的帮助下使用 shell 进程(资源管理器)作为新进程的父进程。代码示例

    ULONG ExecFromShell(_In_opt_ PCWSTR lpApplicationName,
                        _Inout_opt_ PWSTR lpCommandLine)
    {
        if (HWND hwnd = GetShellWindow())
        {
            ULONG dwProcessId, dwThreadId;
            if (dwThreadId = GetWindowThreadProcessId(hwnd, &dwProcessId))
            {
                if (HANDLE hProcess = OpenProcess(PROCESS_CREATE_PROCESS|READ_CONTROL, 
                        FALSE, dwProcessId))
                {
                    PROCESS_INFORMATION pi;
                    STARTUPINFOEXW si { sizeof(si)};
                    SIZE_T s = 0;
                    ULONG dwError;
    
    __0:
                    switch (dwError = InitializeProcThreadAttributeList(
                        si.lpAttributeList, 1, 0, &s) ? NOERROR : GetLastError())
                    {
                    case ERROR_INSUFFICIENT_BUFFER:
                        if (!si.lpAttributeList)
                        {
                            si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)alloca(s);
                            goto __0;
                        }
                        break;
                    case NOERROR:
                        if (UpdateProcThreadAttribute(si.lpAttributeList, 0, 
                            PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
                            &hProcess, sizeof(hProcess), 0, 0))
                        {
                            ULONG cb = 0;
                            SECURITY_ATTRIBUTES sa = { sizeof(sa) };
    
    __1:
                            switch (GetKernelObjectSecurity(hProcess, 
                                DACL_SECURITY_INFORMATION|LABEL_SECURITY_INFORMATION, 
                                sa.lpSecurityDescriptor, cb, &cb) ? NOERROR : GetLastError())
                            {
                            case ERROR_INSUFFICIENT_BUFFER:
                                if (!sa.lpSecurityDescriptor)
                                {
                                    sa.lpSecurityDescriptor = alloca(cb);
                                    goto __1;
                                }
                                break;
                            case NOERROR:
                                if (CreateProcessW(lpApplicationName, lpCommandLine, &sa, &sa, 
                                    FALSE, EXTENDED_STARTUPINFO_PRESENT, 0, 0, &si.StartupInfo, &pi))
                                {
                                    CloseHandle(pi.hThread);
                                    CloseHandle(pi.hProcess);
                                }
                                else
                                {
                                    dwError = GetLastError();
                                }
                                break;
                            }                       
    
                        }
                        else
                        {
                            dwError = GetLastError();
                        }
    
                        DeleteProcThreadAttributeList(si.lpAttributeList);
                        break;
                    }
                    
                    CloseHandle(hProcess);
    
                    return dwError;
                }
    
                return GetLastError();
            }
        }
    
        return ERROR_NOT_FOUND;
    }
    

    【讨论】:

    • @BarmakShemirani - 这不是无限循环。这是我的技术
    • 哦,我明白你在做什么了。如果您只调用两次InitializeProcThreadAttributeList,代码会更少。
    • @BarmakShemirani - 在 src 代码中两次 :) 这不会是更少的代码 - 试试吧。我更喜欢这种风格。这也将在运行时调用两次,但在 src 中只调用一次
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-28
    • 2017-10-29
    • 2016-04-10
    • 1970-01-01
    • 2020-04-07
    相关资源
    最近更新 更多