#include "stdafx.h" /* runas是一个常用的命令,你会用吗? 我不会,但我要探究它的进一步的原理。 其实很简单,参见:http://msdn.microsoft.com/en-us/library/windows/desktop/ms682431(v=vs.85).aspx 注意事项:见注释。 不过要在不同的会话中运行,那就麻烦了。 普通的程序需要提权。 而进程的权限是继承自用户的,所以还要给用户分派权限。 具体的设置可以参考本地安全策略:http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/08bc7712-548c-4308-a49c-d551a4b5e245.mspx?mfr=true。 注意:这些设置还要重启后生效。 所以常用的办法是用服务,服务默认是具有这些权限的。再次郑重说明:不用服务也是可以的。 正好这有解决了服务在Vista及以后系统的编程交互(如:弹出对话框)的问题。 提示:命令行输入空的参数,可以使用双引号,也就是这两个引号之间没有内容,包括空格。 made by correy made at 2014.05.17 email:kouleguan at hotmail dot com homepage:http://correy.webs.com */ #include <windows.h> #include <stdio.h> #include <userenv.h> #pragma comment(lib, "userenv.lib") void DisplayError(LPWSTR pszAPI) { LPVOID lpvMessageBuffer; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&lpvMessageBuffer, 0, NULL); //... now display this string wprintf(L"ERROR: API = %s.\n", pszAPI); wprintf(L" error code = %d.\n", GetLastError()); wprintf(L" message = %s.\n", (LPWSTR)lpvMessageBuffer); LocalFree(lpvMessageBuffer);// Free the buffer allocated by the system ExitProcess(GetLastError()); } void wmain(int argc, WCHAR *argv[]) { if (argc != 4) { wprintf(L"Usage: %s [user@domain] [password] [cmd]", argv[0]); wprintf(L"\n\n"); return; } // TO DO: change NULL to '.' to use local account database HANDLE hToken; if (!LogonUser(argv[1], NULL, argv[2], LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &hToken)) { //必须有密码,不然失败。 DisplayError(L"LogonUser"); } //得到的内容其实就是:The environment block is an array of null-terminated Unicode strings. The list ends with two nulls (\0\0). LPVOID lpvEnv; if (!CreateEnvironmentBlock(&lpvEnv, hToken, TRUE)) { DisplayError(L"CreateEnvironmentBlock"); } //获取用户的文件夹。 WCHAR szUserProfile[256] = L""; DWORD dwSize = sizeof(szUserProfile)/sizeof(WCHAR); if (!GetUserProfileDirectory(hToken, szUserProfile, &dwSize)) {//用户必须登录运行过一次,不必此时这个用户运行着。 DisplayError(L"GetUserProfileDirectory"); } // TO DO: change NULL to '.' to use local account database STARTUPINFO si = {0}; si.cb = sizeof(STARTUPINFO); PROCESS_INFORMATION pi = {0}; if (!CreateProcessWithLogonW(argv[1], NULL, argv[2], LOGON_WITH_PROFILE, NULL, argv[3], CREATE_UNICODE_ENVIRONMENT, lpvEnv, szUserProfile, &si, &pi)) { DisplayError(L"CreateProcessWithLogonW"); } if (!DestroyEnvironmentBlock(lpvEnv)) { DisplayError(L"DestroyEnvironmentBlock"); } CloseHandle(hToken); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); }
2014年5月17日星期六
以另一个用户启动一个进程
订阅:
博文评论 (Atom)
没有评论:
发表评论