CreateProcessAsUser的问题

mcaok 2010-03-04 11:32:36
在服务中运行RunProcess函数以CreateProcessAsUser启动一个进程,用任务管理器查看是以当前用户运行的。但是点击这个进程中的按钮调用SHBrowseForFolder时弹却不出来文件选择对话框。手动运行这个程序时就能弹出文件选择对话框。我觉得可能是CreateProcessAsUser的问题,谁能帮我看一下问题出在哪了。以下是代码。

BOOL RunProcess(LPTSTR lpImage)
{

BOOL bResult;
if(!lpImage)
{
return FALSE;
}
//RaisePrivleges();
HANDLE hToken;
if(!GetTokenByName(hToken,"EXPLORER.EXE"))
{
return FALSE;
}
STARTUPINFO si;
PROCESS_INFORMATION pi;
//LPVOID pEnv = NULL;

ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb= sizeof(STARTUPINFO);
si.lpDesktop = TEXT("winsta0\\default");

SECURITY_ATTRIBUTES sa;
sa.nLength=sizeof(sa);
sa.bInheritHandle=FALSE;
sa.lpSecurityDescriptor=NULL;
//CreateEnvironmentBlock(&pEnv, hToken, TRUE);

bResult= CreateProcessAsUser(hToken,NULL,lpImage,&sa,NULL, FALSE,NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi);


CloseHandle(hToken);
return bResult;

}

...全文
2297 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
minggo1981 2011-05-10
  • 打赏
  • 举报
回复
我也碰到这种问题了,通过CREATEPROCESSASUSER创建的进程,虽然任务管理器查看已经是用户权限了,但是里面执行的结果却是SYSTEM权限的,环境变量什么的都是SYSTEM的。
SiGoYi 2010-03-05
  • 打赏
  • 举报
回复
学习了~~~~~~~~~~~~~~~
mcaok 2010-03-05
  • 打赏
  • 举报
回复
谢谢各位问题已经解决了。加上ulFlags=BIF_USENEWUI 这个,文件选择对话框就显示出来了,但有个问题一直没想明白。为什么在服务中以当前登录用户权限打开一个程序,在这个程序中调用SHBrowseForFolder,如果不指定默认文件夹,就显示不出来文件夹,而且不能指定为桌面。
SiGoYi 2010-03-04
  • 打赏
  • 举报
回复
最后再给你提供点意见,可能是权限太高,服务的权限是session0,如果是在服务中需要模拟成当前用户的权限才能好用!我以前做过类似的问题,感觉在服务程序里,许多在正常程序下可以用的,到了服务里都不行。后来模拟成当前用户权限就可以了。
SiGoYi 2010-03-04
  • 打赏
  • 举报
回复
第二个参数为什么是NULL,应该是你进程的名字吧?你这么做能创建出进程吗?
SiGoYi 2010-03-04
  • 打赏
  • 举报
回复

加上这个代码,有两个地方没有释放
if (pi.hProcess != INVALID_HANDLE_VALUE)
{
CloseHandle(pi.hProcess);
}

if (pi.hThread != INVALID_HANDLE_VALUE)
{
CloseHandle(pi.hThread);
}
SiGoYi 2010-03-04
  • 打赏
  • 举报
回复
我说11楼啊!楼主已经说他创建的线程在任务管理器中可以看到进程的用户名是当前用户了。如果可以看到的话,说明和Token没有关系啊!
skybblue 2010-03-04
  • 打赏
  • 举报
回复
或者你试试这种方法:
void CreateProcess(LPTSTR lpImage)
{
// 为了显示更加复杂的用户界面,我们需要从Session 0创建
// 一个进程,但是这个进程是运行在用户环境下。
// 我们可以使用CreateProcessAsUser实现这一功能。

BOOL bSuccess = FALSE;
STARTUPINFO si = {0};
// 进程信息
PROCESS_INFORMATION pi = {0};
si.cb = sizeof(si);

// 获得当前Session ID
DWORD dwSessionID = WTSGetActiveConsoleSessionId();

HANDLE hToken = NULL;
// 获得当前Session的用户令牌
if (WTSQueryUserToken(dwSessionID, &hToken) == FALSE)
{
goto Cleanup;
}

// 复制令牌
HANDLE hDuplicatedToken = NULL;
if (DuplicateTokenEx(hToken,
MAXIMUM_ALLOWED, NULL,
SecurityIdentification, TokenPrimary,
&hDuplicatedToken) == FALSE)
{
goto Cleanup;
}

// 创建用户Session环境
LPVOID lpEnvironment = NULL;
if (CreateEnvironmentBlock(&lpEnvironment,
hDuplicatedToken, FALSE) == FALSE)
{
goto Cleanup;
}

// 在复制的用户Session下执行应用程序,创建进程。
// 通过这个进程,就可以显示各种复杂的用户界面了
if (CreateProcessAsUser(hDuplicatedToken,
lpImage, NULL, NULL, NULL, FALSE,
NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT,
lpEnvironment, NULL, &si, &pi) == FALSE)
{
goto Cleanup;
}

CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
bSuccess = TRUE;

// 清理工作

Cleanup:
/*if (!bSuccess)
{
ShowMessage(L"无法创建复杂UI", L"错误");
} */

if (hToken != NULL)
CloseHandle(hToken);
if (hDuplicatedToken != NULL)
CloseHandle(hDuplicatedToken);
if (lpEnvironment != NULL)
DestroyEnvironmentBlock(lpEnvironment);
}
skybblue 2010-03-04
  • 打赏
  • 举报
回复
我觉得可能是你GetTokenByName函数的问题,我用下面方法取得的Token创建的进程可以显示界面.
HANDLE CRkzSmsServiceModule::GetToken(DWORD dwProcessID)
{
HANDLE hProcess = NULL;
HANDLE hToken = NULL;
HANDLE g_hToken = NULL;

PSECURITY_DESCRIPTOR pSD = NULL;

try {
// Get the handle to the process
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwProcessID);
if (hProcess == NULL) return NULL;

// Get the token (All access so we can change and launch things
if (!OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken))
{
CloseHandle(hProcess);
return NULL;
}

// Get memory for an SD
pSD = (PSECURITY_DESCRIPTOR) GlobalAlloc(GPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
if (pSD == NULL)
{
CloseHandle(hToken);
CloseHandle(hProcess);
return NULL;
}

// Initialize it
if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
{
GlobalFree(pSD);
CloseHandle(hToken);
CloseHandle(hProcess);
return NULL;
}

// Add a NULL DACL to the security descriptor..
if (!SetSecurityDescriptorDacl(pSD, TRUE, (PACL) NULL, FALSE))
{
GlobalFree(pSD);
CloseHandle(hToken);
CloseHandle(hProcess);
return NULL;
}

// We made the security descriptor just in case they want a duplicate.
// We make the duplicate have all access to everyone.
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = pSD;
sa.bInheritHandle = TRUE;

// If the user chooses not to copy the token, then changes made to it
// will effect the owning process
// if (IDNO == ::MessageBox(NULL, TEXT("Would you like to make a copy of ")
// TEXT("this process token?\n(Selecting \"No\" will cause the ")
// TEXT("\"AdjustToken\" and \"SetToken\"\nfeatures to affect the ")
// TEXT("owning process.) "), TEXT("Duplicate Token?"), MB_YESNO))

// Duplicate the token
if (!DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, &sa,
SecurityImpersonation, TokenPrimary, &g_hToken))
{
CloseHandle(hToken);
CloseHandle(hProcess);
GlobalFree(pSD);
return NULL;
}
}
catch(...)
{}

CloseHandle(hToken);
CloseHandle(hProcess);
GlobalFree(pSD);
return g_hToken;
}

创建进程部分
DWORD dwPID = GetProcessIdByName(_T("explorer.exe"));
if(dwPID != 0)
{
HANDLE hToken = GetToken(dwPID);
if(hToken != NULL)
{
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);

TCHAR szFilePath[MAX_PATH];
::GetModuleFileName(NULL, szFilePath, MAX_PATH);
*_tcsrchr(szFilePath, _T('\\')) = 0;
_tcscat_s(szFilePath, MAX_PATH, _T("\\RkzSmsServer.exe"));

// Create a new process with our current token
PROCESS_INFORMATION pi;
if (CreateProcessAsUser(hToken, NULL, szFilePath, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
CloseHandle(hToken);
}
}
另一个我觉得可能是你创建进程标志的问题,把FALSE,NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE去掉试试
SiGoYi 2010-03-04
  • 打赏
  • 举报
回复
要是在不好用在

si.dwFlags = STARTF_USESHOWWINDOW;下

加这句
si.wShowWindow = SW_SHOW;
SiGoYi 2010-03-04
  • 打赏
  • 举报
回复
加下这个试一下,知道加哪吧!
si.dwFlags = STARTF_USESHOWWINDOW;
SiGoYi 2010-03-04
  • 打赏
  • 举报
回复
朋友,一般来说用CreateProcessAsUser API只要是第一个参数token传的是当前用户的token那么在任务管理器中的用户名一定是当前用户这没有错。但是你通过调用CreateProcessAsUser启动进程和你直接启动进程应该是一样的啊!应该没有什么特别。在这里我只能帮你顶了。我个人认为应该没有问题,不应该出现你说的出现的问题。
最后帮顶~~~~~~~~~~~~~~~~~~~~~~~~高手请来帮忙。
mcaok 2010-03-04
  • 打赏
  • 举报
回复
在进程里初始化BROWSEINFO结构时,添加ulFlags=BIF_USENEWUI 就能显示对话框了。但文件夹显示部分是空白。什么也没有。
mcaok 2010-03-04
  • 打赏
  • 举报
回复
引用 5 楼 sigoyi 的回复:
感觉应该没有问题啊!实在不行调用GetLastError看看错误码!

试过。没有返回错误。就是执行SHBrowseForFolder没显示出对话框,本来应该在执行SHBrowseForFolder的时候程序会暂停等待用户选择文件夹,然后再往下执行。调试的结果是执行完SHBrowseForFolder没有显示对话框而是直接往下执行了。
SiGoYi 2010-03-04
  • 打赏
  • 举报
回复
感觉应该没有问题啊!实在不行调用GetLastError看看错误码!
mcaok 2010-03-04
  • 打赏
  • 举报
回复
引用 3 楼 sigoyi 的回复:
最后再给你提供点意见,可能是权限太高,服务的权限是session0,如果是在服务中需要模拟成当前用户的权限才能好用!我以前做过类似的问题,感觉在服务程序里,许多在正常程序下可以用的,到了服务里都不行。后来模拟成当前用户权限就可以了。

我是用第三个参数来传递程序名的。这段代码就是以当前用户权限启动的程序,在任务管理器中已经显示是当前用户了。

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧