在没有新控制台的情况下使用 CreateProcessWithLogonW() 执行 CMD.EXE
Posted
技术标签:
【中文标题】在没有新控制台的情况下使用 CreateProcessWithLogonW() 执行 CMD.EXE【英文标题】:Execute CMD.EXE with CreateProcessWithLogonW() without a new console 【发布时间】:2020-04-06 20:28:01 【问题描述】:我必须使用CreateProcessWithLogonW()
运行cmd.exe
,但在我的程序上下文中无需创建另一个控制台,但MSDN 说CREATE_NEW_CONSOLE
标志已默认设置。如何取消设置此标志,以便此 API 不会为我的子进程创建新窗口?
以下代码显示了此 API 在我的程序中的使用方式。我不希望新程序在新控制台中运行,但我找不到解决方案。
BOOL status = FALSE;
DWORD process_flags = 0 | arg_process_flags;
DWORD logon_flags = 0 | arg_logon_flags;
PTSTR duplicate_command_Line;
PPROCESS_INFORMATION ptr_process_info;
STARTUPINFO startup_info;
RtlZeroMemory(&startup_info, sizeof(STARTUPINFO));
startup_info.cb = sizeof(STARTUPINFO);
if (ptr_process_info = arg_process_infos ? arg_process_infos : (PPROCESS_INFORMATION)LocalAlloc(LPTR, sizeof(PROCESS_INFORMATION)))
if (duplicate_command_Line = _wcsdup(arg_command_Line))
switch (arg_type)
case KULL_M_PROCESS_CREATE_NORMAL:
status = CreateProcess(NULL, duplicate_command_Line, NULL, NULL, FALSE, process_flags, NULL, NULL, &startup_info, ptr_process_info);
break;
case KULL_M_PROCESS_CREATE_USER:
status = CreateProcessAsUser(arg_user_token, NULL, duplicate_command_Line, NULL, NULL, FALSE, process_flags, NULL, NULL, &startup_info, ptr_process_info);
break;
case KULL_M_PROCESS_CREATE_LOGON:
status = CreateProcessWithLogonW(arg_user, arg_domain, arg_password, logon_flags, NULL, duplicate_command_Line, process_flags, NULL, NULL, &startup_info, ptr_process_info);
break;
if (status && (arg_auto_close_handle || !arg_process_infos))
CloseHandle(ptr_process_info->hThread);
CloseHandle(ptr_process_info->hProcess);
if (!arg_process_infos)
LocalFree(ptr_process_info);
free(duplicate_command_Line);
【问题讨论】:
附带说明,您可以在错误的地方调用LocalFree(ptr_process_info)
。如果arg_process_infos
为空并且_wcsdup()
返回空,则您泄漏ptr_process_info
。 LocalFree()
需要在 if (ptr_process_info ...)
块内调用,而不是在 if (duplicate_command_Line ...)
块内调用。
当您通过CreateProcessWithLogonW
启动进程时,它将在另一个登录会话中运行,即使您使用与当前运行相同的用户名。从另一端系统执行/使用 conhost.exe 从与控制台应用程序相同的登录会话。因此新进程无法使用您的控制台 (conhost.exe)。因此,即使您没有设置CREATE_NEW_CONSOLE
,系统也会像设置了一样运行。
【参考方案1】:
你可以redirected input and output of child process
这是我的测试程序(去掉错误检查)。
家长:
#include <windows.h>
#include <iostream>
#define BUFSIZE 4096
void main()
printf("in Parent \n");
HANDLE R_In, R_Out, R_err, W_In, W_Out, W_err;
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
SECURITY_ATTRIBUTES saAttr;
BOOL bSuccess;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
CreatePipe(&R_In, &W_In, &saAttr, 0);
CreatePipe(&R_Out, &W_Out, &saAttr, 0);
CreatePipe(&R_err, &W_err, &saAttr, 0);
PROCESS_INFORMATION process_info;
STARTUPINFO startup_info;
RtlZeroMemory(&startup_info, sizeof(STARTUPINFO));
startup_info.cb = sizeof(STARTUPINFO);
startup_info.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
startup_info.wShowWindow = SW_HIDE;
startup_info.hStdInput = R_In;
startup_info.hStdOutput = W_Out;
startup_info.hStdError = W_err;
BOOL ret = CreateProcessWithLogonW(L"username",L"domain",L"password", 0,L"ChildProcess.exe",NULL, CREATE_NO_WINDOW,NULL,NULL,&startup_info,&process_info);
CloseHandle(R_In);
CloseHandle(W_Out);
CloseHandle(W_err);
CHAR chBuf[BUFSIZE];
DWORD dwRead, dwWritten;
bSuccess = ReadFile(hStdin, chBuf, BUFSIZE, &dwRead, NULL);
bSuccess = WriteFile(W_In, chBuf, dwRead, &dwWritten, NULL);
while (1)
bSuccess = ReadFile(R_Out, chBuf, BUFSIZE, &dwRead, NULL);
if (bSuccess == 0 & GetLastError() == ERROR_BROKEN_PIPE) // child process exit.
break;
bSuccess = WriteFile(hStdout, chBuf, dwRead, &dwWritten, NULL);
WaitForSingleObject(process_info.hProcess, INFINITE);
printf("Parent exit\n");
孩子:
#include <windows.h>
#include <iostream>
#define BUFSIZE 4096
#pragma warning(disable : 4996)
void main()
CHAR chBuf[BUFSIZE];
scanf("%s", chBuf);
printf("in Child %s\n", chBuf);
printf("Child exit\n");
return;
结果:
【讨论】:
那么当控制台程序提示输入密码或要求逐个字符输入时会发生什么?【参考方案2】:你的意思是你不想创建一个新窗口?
尝试startup_info.dwFlags = STARTF_USESHOWWINDOW;startup_info.wShowWindow = SW_HIDE;
则不会创建窗口。
【讨论】:
我希望新进程能够在父环境中执行,而不是创建另一个控制台。 啊,对不起,我没有正确理解。 @KLightning - 如果您使用 CreateProcessWithLogonW - 子进程将在 新登录会话 中执行。它不能在父环境中执行【参考方案3】:已经有一段时间了,但是通过 DETACHED_PROCESS
应该可以工作。
如果没有,您可以调用CreateProcessWithLogonW
传递一个您提供的win32 二进制文件(可能是您自己的带有不同选项的),然后调用CreateProcess
打开cmd.exe
而不传递CREATE_NEW_CONSOLE
。
除非你已经是管理员,否则在同一个控制台中创建是完全不可能的,如果你是管理员,那么你最好不要使用它是一种神秘的技术。
【讨论】:
“通过 DETACHED_PROCESS 应该可以工作” - 不。 This value cannot be used with CREATE_NEW_CONSOLE. - 在这种情况下,我们得到错误参数无效。使用第二种变体,我们可以在没有控制台的情况下运行进程。但不使用与父级相同的控制台 @RbMm:从问题中 OP 想要与父级相同的控制台并不是很明显,但如果他这样做了,他需要重新考虑他想要做什么。以上是关于在没有新控制台的情况下使用 CreateProcessWithLogonW() 执行 CMD.EXE的主要内容,如果未能解决你的问题,请参考以下文章
在没有“应用签名”的情况下为 Google Play 商店中的应用设置新的上传密钥
如何在没有动画的情况下将 UISearchController 设置为活动?