Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.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++ Shell执行将窗口带到前面_C++_C_Windows - Fatal编程技术网

C++ Shell执行将窗口带到前面

C++ Shell执行将窗口带到前面,c++,c,windows,C++,C,Windows,我正在使用这个函数从我的MSI调用一个可执行文件。但是,可执行文件的窗口隐藏在我的MSI窗口后面。有没有办法把它带到前线 在调用ShellExecute之前,我尝试过最小化所有窗口,但这仍然没有将可执行窗口带到最前面 extern "C" UINT __stdcall InstallDrivers(MSIHANDLE hInstall) { HRESULT hr = S_OK; UINT er = ERROR_SUCCESS; HANDLE hFile = INVALID_H

我正在使用这个函数从我的MSI调用一个可执行文件。但是,可执行文件的窗口隐藏在我的MSI窗口后面。有没有办法把它带到前线

在调用
ShellExecute
之前,我尝试过最小化所有窗口,但这仍然没有将可执行窗口带到最前面

extern "C" UINT __stdcall InstallDrivers(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
HANDLE hFile = INVALID_HANDLE_VALUE;
BYTE* pbData = NULL;
DWORD cbData = 0;
char pwzFilename[MAX_PATH], szDriverType[MAX_PATH], pwzSentinelFilename[MAX_PATH], szIsInstalled[MAX_PATH];
LPWSTR szValueBuf = NULL, szIsHaspInstalled = NULL, szIsSentinelInstalled = NULL;

hr = WcaInitialize(hInstall, "InstallDrivers");
ExitOnFailure(hr, "Failed to initialize");

WcaLog(LOGMSG_STANDARD, "Initialized.");
WcaLog(LOGMSG_STANDARD, "%s", szValueBuf);
CreateDirectory("C:\\Temp", NULL);

strcpy_s(pwzFilename, "C:\\Temp\\HASPUserSetup.exe");

hr = ExtractBinary(L"Hasp", &pbData, &cbData);
ExitOnFailure(hr, "failed to extract binary data");

if ((hFile = CreateFile(pwzFilename, GENERIC_WRITE,FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) 
{
    PMSIHANDLE hRecord = MsiCreateRecord(0);
    MsiRecordSetString(hRecord, 0, TEXT("Could not create new temporary file"));
    MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_ERROR + MB_OK), hRecord);
    return ERROR_INSTALL_USEREXIT;  
} 

DWORD cbWritten = 0;
if ( !WriteFile(hFile, pbData, cbData, &cbWritten, NULL) )
{
    PMSIHANDLE hRecord = MsiCreateRecord(0);
    MsiRecordSetString(hRecord, 0, TEXT("Could not write to file"));
    MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_ERROR + MB_OK), hRecord);
    return ERROR_INSTALL_USEREXIT;
}

CloseHandle(hFile);

strcpy_s(pwzSentinelFilename, "C:\\Temp\\sentinel_setup.exe");
hr = ExtractBinary(L"Sentinel", &pbData, &cbData);
ExitOnFailure(hr, "failed to extract binary data");

if ((hFile = CreateFile(pwzSentinelFilename, GENERIC_WRITE,FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) 
{
    PMSIHANDLE hRecord = MsiCreateRecord(0);
    MsiRecordSetString(hRecord, 0, TEXT("Could not create new temporary file"));
    MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_ERROR + MB_OK), hRecord);
    return ERROR_INSTALL_USEREXIT;  
} 


if ( !WriteFile(hFile, pbData, cbData, &cbWritten, NULL) )
{
    PMSIHANDLE hRecord = MsiCreateRecord(0);
    MsiRecordSetString(hRecord, 0, TEXT("Could not write to file"));
    MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_ERROR + MB_OK), hRecord);
    return ERROR_INSTALL_USEREXIT;
}

CloseHandle(hFile);

hr = WcaGetProperty(L"DRIVER", &szValueBuf);
ExitOnFailure(hr, "failed to get driver info");

wcstombs(szDriverType, szValueBuf, 260);
if (strcmp(szDriverType, "Hasp") == 0)
{   

    hr = WcaGetProperty(L"SENTINELINSTALLED", &szIsSentinelInstalled);
    ExitOnFailure(hr, "failed to get driver info");
    wcstombs(szIsInstalled, szValueBuf, 260);
    if (strcmp(szIsInstalled, "Sentinel Protection Installer 7.6.5") == 0)
    {
    ShellExecute(NULL, "open",  pwzSentinelFilename, NULL, NULL, SW_SHOWNORMAL);
    }
    ShellExecute(NULL, "open",  pwzFilename, NULL, NULL, SW_SHOWNORMAL);
}else
{
    hr = WcaGetProperty(L"HASPINSTALLED", &szIsHaspInstalled);
    ExitOnFailure(hr, "failed to get driver info");
    wcstombs(szIsInstalled, szIsHaspInstalled, 260);
    if (strcmp(szIsInstalled, "Sentinel Runtime") == 0)
    {
    ShellExecute(NULL, "open",  pwzFilename, NULL, NULL, SW_SHOWNORMAL);
    }
    ShellExecute(NULL, "open",  pwzSentinelFilename, NULL, NULL, SW_SHOWNORMAL);
}
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
更新代码:

extern "C" UINT __stdcall InstallDrivers(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
HANDLE hFile = INVALID_HANDLE_VALUE;
BYTE* pbData = NULL;
DWORD cbData = 0;
char pwzFilename[MAX_PATH], szDriverType[MAX_PATH], pwzSentinelFilename[MAX_PATH], szIsInstalled[MAX_PATH];
LPWSTR szValueBuf = NULL, szIsHaspInstalled = NULL, szIsSentinelInstalled = NULL;
SHELLEXECUTEINFO ShExecInfo;

ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = NULL;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = NULL;
ShExecInfo.lpParameters = NULL;
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = SW_SHOWNORMAL;
ShExecInfo.hInstApp = NULL;

hr = WcaInitialize(hInstall, "InstallDrivers");
ExitOnFailure(hr, "Failed to initialize");

WcaLog(LOGMSG_STANDARD, "Initialized.");
WcaLog(LOGMSG_STANDARD, "%s", szValueBuf);
CreateDirectory("C:\\Temp", NULL);

strcpy_s(pwzFilename, "C:\\Temp\\HASPUserSetup.exe");

hr = ExtractBinary(L"Hasp", &pbData, &cbData);
ExitOnFailure(hr, "failed to extract binary data");

if ((hFile = CreateFile(pwzFilename, GENERIC_WRITE,FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) 
{
    PMSIHANDLE hRecord = MsiCreateRecord(0);
    MsiRecordSetString(hRecord, 0, TEXT("Could not create new temporary file"));
    MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_ERROR + MB_OK), hRecord);
    return ERROR_INSTALL_USEREXIT;  
} 

DWORD cbWritten = 0;
if ( !WriteFile(hFile, pbData, cbData, &cbWritten, NULL) )
{
    PMSIHANDLE hRecord = MsiCreateRecord(0);
    MsiRecordSetString(hRecord, 0, TEXT("Could not write to file"));
    MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_ERROR + MB_OK), hRecord);
    return ERROR_INSTALL_USEREXIT;
}

CloseHandle(hFile);

strcpy_s(pwzSentinelFilename, "C:\\Temp\\sentinel_setup.exe");
hr = ExtractBinary(L"Sentinel", &pbData, &cbData);
ExitOnFailure(hr, "failed to extract binary data");

if ((hFile = CreateFile(pwzSentinelFilename, GENERIC_WRITE,FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) 
{
    PMSIHANDLE hRecord = MsiCreateRecord(0);
    MsiRecordSetString(hRecord, 0, TEXT("Could not create new temporary file"));
    MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_ERROR + MB_OK), hRecord);
    return ERROR_INSTALL_USEREXIT;  
} 


if ( !WriteFile(hFile, pbData, cbData, &cbWritten, NULL) )
{
    PMSIHANDLE hRecord = MsiCreateRecord(0);
    MsiRecordSetString(hRecord, 0, TEXT("Could not write to file"));
    MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_ERROR + MB_OK), hRecord);
    return ERROR_INSTALL_USEREXIT;
}

CloseHandle(hFile);

hr = WcaGetProperty(L"DRIVER", &szValueBuf);
ExitOnFailure(hr, "failed to get driver info");

wcstombs(szDriverType, szValueBuf, 260);
if (strcmp(szDriverType, "Hasp") == 0)
{   

    hr = WcaGetProperty(L"SENTINELINSTALLED", &szIsSentinelInstalled);
    ExitOnFailure(hr, "failed to get driver info");
    wcstombs(szIsInstalled, szValueBuf, 260);
    if (strcmp(szIsInstalled, "Sentinel Protection Installer 7.6.5") == 0)
    {
        AllowSetForegroundWindow(ASFW_ANY);
        ShExecInfo.lpFile = pwzSentinelFilename;
        ShellExecuteEx(&ShExecInfo);
        /*ShellExecute(NULL, "open",  pwzSentinelFilename, NULL, NULL, SW_SHOWNORMAL);*/
    }
    AllowSetForegroundWindow(ASFW_ANY);
    ShExecInfo.lpFile = pwzFilename;
    ShellExecuteEx(&ShExecInfo);

    /*ShellExecute(NULL, "open",  pwzFilename, NULL, NULL, SW_SHOWNORMAL);*/
}else
{
    hr = WcaGetProperty(L"HASPINSTALLED", &szIsHaspInstalled);
    ExitOnFailure(hr, "failed to get driver info");
    wcstombs(szIsInstalled, szIsHaspInstalled, 260);
    if (strcmp(szIsInstalled, "Sentinel Runtime") == 0)
    {
        AllowSetForegroundWindow(ASFW_ANY);
        /*ShellExecute(NULL, "open",  pwzFilename, NULL, NULL, SW_SHOWNORMAL);*/
        ShExecInfo.lpFile = pwzFilename;
        ShellExecuteEx(&ShExecInfo);
    }
    AllowSetForegroundWindow(ASFW_ANY);
    ShExecInfo.lpFile = pwzSentinelFilename;
    ShellExecuteEx(&ShExecInfo);
    /*  ShellExecute(NULL, "open",  pwzSentinelFilename, NULL, NULL, SW_SHOWNORMAL);*/
}
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}

Windows不允许进程抢夺前台窗口,除非用户启动它们。这是为了避免像说服用户在错误的窗口中键入银行详细信息这样的事情。但是,当前前台进程可以将权限传递给另一个进程来执行此操作。有关详细信息,请参阅。为此,必须为将成为前台的进程提供进程id,而ShellExecute不提供该id。但是,如果切换到使用,则可以从SHELLEXECUTEINFO结构上的hProcess成员处获取此信息

然后你可以调用你的新流程,它将被允许。否则它就会在任务栏上开始闪烁

编辑

如果您的初始应用程序是前台应用程序,并且您从该应用程序启动子流程,则子流程应自动成为前台,如这些函数的文档中所述

下面是一个示例,说明如何选择启用和设置另一个应用程序,使其成为前台窗口。在本例中,它只创建一个文本文件,并使用
open
动词调用ShellExecuteEx。我们必须等待子进程开始运行并准备好它的窗口,然后我们可以从进程ID定位窗口,授予它权限,并将其窗口设置为前台。在这种情况下,启动的记事本(或任何你的.txt文件的“打开”动词)无论如何都是前台的。如果您单独运行一个记事本进程,并在该进程的进程ID中替换我们通常放在子进程ID中的进程ID,那么我们可以使另一个进程成为前台进程--一个不属于进程树的进程。这可以用Visual C++编写,用< Cl> Cl- NoLogo -W3-O2-MD FGZTest.CPP >生成FGZTest.exe .<
#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <shellapi.h>

#pragma comment(lib, "shell32")
#pragma comment(lib, "user32")

static void PrintError(LPCTSTR szPrefix, DWORD dwError);
static BOOL CALLBACK OnGetWindowByProcess(HWND hwnd, LPARAM lParam);

typedef struct {
    DWORD pid;
    HWND hwnd;
} WINDOWPROCESSINFO;

int _tmain(int argc, TCHAR *argv[])
{
    SHELLEXECUTEINFO sxi = {0};
    sxi.cbSize = sizeof(sxi);
    sxi.nShow = SW_SHOWNORMAL;

    FILE *fp = NULL;
    _tfopen_s(&fp, _T("junk.txt"), _T("wt"));
    _fputts(_T("Example text file\n"), fp);
    fclose(fp);

    sxi.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NOASYNC | SEE_MASK_WAITFORINPUTIDLE;
    sxi.lpVerb = _T("open");
    sxi.lpFile = _T("junk.txt");
    if (!ShellExecuteEx(&sxi))
        PrintError(_T("ShellExecuteEx"), GetLastError());
    else
    {
        WINDOWPROCESSINFO info;
        info.pid = GetProcessId(sxi.hProcess); // SPECIFY PID
        info.hwnd = 0;
        AllowSetForegroundWindow(info.pid);
        EnumWindows(OnGetWindowByProcess, (LPARAM)&info);
        if (info.hwnd != 0)
        {
            SetForegroundWindow(info.hwnd);
            SetActiveWindow(info.hwnd);
        }
        CloseHandle(sxi.hProcess);

    }
    return 0;
}

static BOOL CALLBACK OnGetWindowByProcess(HWND hwnd, LPARAM lParam)
{
    WINDOWPROCESSINFO *infoPtr = (WINDOWPROCESSINFO *)lParam;
    DWORD check = 0;
    BOOL br = TRUE;
    GetWindowThreadProcessId(hwnd, &check);
    _tprintf(_T("%x %x %x\n"), hwnd, check, infoPtr->pid);
    if (check == infoPtr->pid)
    {
        _tprintf(_T("found window %x for process id %x\n"), hwnd, check);
        infoPtr->hwnd = hwnd;
        br = FALSE;
    }
    return br;
}

static void
PrintError(LPCTSTR szPrefix, DWORD dwError)
{
    LPTSTR lpsz = NULL;
    DWORD cch = 0;

    cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
                        | FORMAT_MESSAGE_FROM_SYSTEM
                        | FORMAT_MESSAGE_IGNORE_INSERTS,
                        NULL, dwError, LANG_NEUTRAL, (LPTSTR)&lpsz, 0, NULL);
    if (cch < 1) {
        cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
                            | FORMAT_MESSAGE_FROM_STRING
                            | FORMAT_MESSAGE_ARGUMENT_ARRAY,
                            _T("Code 0x%1!08x!"),
                            0, LANG_NEUTRAL, (LPTSTR)&lpsz, 0,
                            (va_list*)&dwError);
    }
    _ftprintf(stderr, _T("%s: %s"), szPrefix, lpsz);
    LocalFree((HLOCAL)lpsz);
}
#定义严格的
#定义WIN32_精益_和_平均值
#包括
#包括
#包括
#包括
#pragma注释(lib,“shell32”)
#pragma注释(lib,“user32”)
静态无效打印错误(LPCTSTR szPrefix,DWORD dwError);
静态BOOL回调OnGetWindowByProcess(HWND-HWND,LPARAM-LPARAM);
类型定义结构{
德沃德pid;
HWND-HWND;
}WINDOWPROCESSINFO;
int_tmain(int argc,TCHAR*argv[])
{
SHELLEXECUTEINFO sxi={0};
sxi.cbSize=sizeof(sxi);
sxi.nShow=SW_SHOWNORMAL;
FILE*fp=NULL;
_tfopen_s(&fp,_T(“junk.txt”),_T(“wt”);
_fputts(_T(“示例文本文件”),fp;
fclose(fp);
sxi.fMask=请参阅_MASK_NOCLOSEPROCESS |请参阅_MASK_NOASYNC |请参阅_MASK_waitforinput;
sxi.lpVerb=_T(“打开”);
sxi.lpFile=_T(“junk.txt”);
如果(!ShellExecuteEx(&sxi))
PrintError(_T(“ShellExecuteEx”),GetLastError();
其他的
{
WINDOWPROCESSINFO;
info.pid=GetProcessId(sxi.hProcess);//指定pid
info.hwnd=0;
AllowSetForegroundWindow(信息pid);
EnumWindows(OnGetWindowByProcess、(LPRAM)和信息);
如果(info.hwnd!=0)
{
SetForegroundWindow(info.hwnd);
SetActiveWindow(info.hwnd);
}
CloseHandle(sxi.hProcess);
}
返回0;
}
静态BOOL回调OnGetWindowByProcess(HWND HWND,LPARAM LPARAM)
{
WINDOWPROCESSINFO*infoPtr=(WINDOWPROCESSINFO*)LPRAM;
DWORD校验=0;
布尔br=真;
GetWindowThreadProcessId(hwnd,检查和检查);
_tprintf(_T(“%x%x%x\n”)、hwnd、check、infoPtr->pid;
如果(检查==infoPtr->pid)
{
_tprintf(_T(“为进程id%x找到窗口%x\n”),hwnd,check);
infoPtr->hwnd=hwnd;
br=假;
}
返回br;
}
静态空隙
打印错误(LPCTSTR szPrefix,DWORD dwError)
{
LPTSTR lpsz=NULL;
DWORD cch=0;
cch=格式化消息(格式化消息分配缓冲区
|格式化来自\u系统的\u消息\u
|格式化\u消息\u忽略\u插入,
NULL,dwError,LANG_中立,(LPTSTR)和lpsz,0,NULL);
如果(cch<1){
cch=格式化消息(格式化消息分配缓冲区
|格式化来自字符串的消息
|格式化\u消息\u参数\u数组,
_T(“代码0x%1!08x!”),
0,LANG_空档(LPTSTR)和lpsz,0,
(va_列表*)&dwError);
}
_ftprintf(stderr,_T(“%s:%s”)、szPrefix、lpsz);
本地自由((本地)lpsz);
}

您的MSI窗口是否“始终在顶部”?@Massa,是的,可执行文件在其下方运行。您好,谢谢我已将函数更改为使用
ShellExecuteEx
,但我不确定要将哪个参数传递到
SetForegroundWindow
函数中。您能帮助我吗?通常,您正在启动的应用程序会在其自己的窗口句柄上执行SetForeGroundIndow。这被窗口管理器拒绝,取而代之的是任务栏上会出现一个闪烁的图标。但是,如果上面的函数调用AllowSetForeGroundIndow传递子进程的进程id,则将允许SetForeGroundIndow调用。SetForeGroundIndow文档中讨论了这一点。如果你不能很好地控制孩子,你可以尝试用SW_HIDE启动它,然后显示给予此权限的窗口。我用新代码更新了我的问题。然而,我仍然有同样的问题,不确定我们下一步会去哪里。如果您能提供任何帮助,我将不胜感激。非常感谢……:)我现在还不能奖励奖金,但如果它允许的话,我会奖励的。这段代码假设
ShellExecuteEx
将返回一个进程句柄,在很多情况下可能不会。