场景
- 当Windows app以管理员模式启动时, 可以做一下管理员模式下的操作, 比如安装驱动, 扫描磁盘等. 可是自从vista 开始管理员模式启动关程序必然会弹出UAC对话框. 如果每启动一个需要管理员模式启动的exe都弹出一个对话框的话会让用户觉得程序不安全,而且弹出多了也会对用户体验有影响.
- 如果弹出UAC授权只出现一次, 之后需要UAC授权的默认都允许的话不是更好么. 这里有一个常见方案就是先启动一个UAC授权的AppService, 之后由这个AppService启动其他admin程序. 这样其他程序就不会弹出UAC窗口了.
说明
- 管理员启动的程序,如果他也CreateProcess启动了其他程序那么其他程序默认也继承了该管理员权限, 即也是管理员模式,但是不会再弹出UAC对话框.
Creates a new process and its primary thread. The new process runs in the security context of the calling process.
- 创建一个service在后台运行, 这个service负责启动其他程序.
例子
#include "stdafx.h"
#include <vector>
#include <Windows.h>
#include <iostream>
std::string ToCommandLineArg(const std::vector<std::string>& array)
{
std::string line;
int size = array.size();
for(int i = 0; i < size; ++i)
{
line.append(1,0x20).append(array[i]);
}
return line;
}
wchar_t* Utf82Unicode(const char* str)
{
int dwUnicodeLen = MultiByteToWideChar(CP_UTF8,0,str,-1,NULL,0);
if(!dwUnicodeLen)
{
return wcsdup(L"\0");
}
size_t num = dwUnicodeLen*sizeof(wchar_t);
wchar_t *pwText = (wchar_t*)malloc(num+2);
memset(pwText,0,num+2);
MultiByteToWideChar(CP_UTF8,0,str,-1,pwText,dwUnicodeLen);
return pwText;
}
bool ExecuteCommandNoWait(const char* command1,std::vector<std::string> args)
{
std::string command_all(command1);
std::string arg_all = ToCommandLineArg(args);
command_all.append(" ").append(arg_all);
command1 = command_all.c_str();
std::cout << "command: " << command1 << std::endl;
wchar_t* command = Utf82Unicode(command1);
STARTUPINFOW startupInfo = {sizeof(STARTUPINFOW)};
GetStartupInfoW(&startupInfo);
startupInfo.dwFlags=0;
startupInfo.wShowWindow=SW_SHOWDEFAULT;
bool ret = true;
PROCESS_INFORMATION info;
wchar_t* wlpcmd = wcsdup(command);
if (CreateProcessW(NULL , wlpcmd , NULL , NULL , TRUE , CREATE_NEW_CONSOLE, NULL
, NULL , &startupInfo, &info))
{
CloseHandle(info.hProcess);
CloseHandle(info.hThread);
}else
{
ret = false;
}
free(wlpcmd);
free(command);
return ret;
}
int _tmain(int argc, _TCHAR* argv[])
{
std::cout << "_tmain" << std::endl;
std::vector<std::string> args;
ExecuteCommandNoWait("C:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Common7\\IDE\\devenv.exe",args);
args.push_back("-k");
args.push_back("dir");
ExecuteCommandNoWait("C:\\Windows\\System32\\cmd.exe",args);
return 0;
}