我在这里遇到了严重的问题。我需要通过C ++执行CMD命令行,而不显示控制台窗口。所以我不能用 system(cmd)
,因为窗口将显示。
我努力了 winExec(cmd, SW_HIDE)
,但这也不起作用。 CreateProcess
是我试过的另一个。但是,这适用于运行程序或批处理文件。
我结束了尝试 ShellExecute
:
ShellExecute( NULL, "open",
"cmd.exe",
"ipconfig > myfile.txt",
"c:\projects\b",
SW_SHOWNORMAL
);
任何人都可以看到上述代码有什么问题吗?我用过 SW_SHOWNORMAL
直到我知道这是有效的。
我真的需要一些帮助。没有任何事情发生,我已经尝试了很长一段时间。任何人都可以给出的任何建议都会很棒:)
将输出重定向到您自己的管道是一个更整洁的解决方案,因为它避免创建输出文件,但这工作正常:
ShellExecute(0, "open", "cmd.exe", "/C ipconfig > out.txt", 0, SW_HIDE);
您没有看到cmd窗口,并且输出按预期重定向。
你的代码可能失败了(除了 /C
因为你指定路径为 "c:\projects\b"
而不是 "c:\\projects\\b"
。
你应该用 CreateProcess的 上 cmd.exe
随着 /C
用于隧道ipconfig命令的参数。 >在命令行上本身不起作用。你必须 以编程方式重定向标准输出。
这是我的DosExec函数的实现,它允许(静默地)执行任何DOS命令并将生成的输出检索为unicode字符串。
// Convert an OEM string (8-bit) to a UTF-16 string (16-bit)
#define OEMtoUNICODE(str) CHARtoWCHAR(str, CP_OEMCP)
/* Convert a single/multi-byte string to a UTF-16 string (16-bit).
We take advantage of the MultiByteToWideChar function that allows to specify the charset of the input string.
*/
LPWSTR CHARtoWCHAR(LPSTR str, UINT codePage) {
size_t len = strlen(str) + 1;
int size_needed = MultiByteToWideChar(codePage, 0, str, len, NULL, 0);
LPWSTR wstr = (LPWSTR) LocalAlloc(LPTR, sizeof(WCHAR) * size_needed);
MultiByteToWideChar(codePage, 0, str, len, wstr, size_needed);
return wstr;
}
/* Execute a DOS command.
If the function succeeds, the return value is a non-NULL pointer to the output of the invoked command.
Command will produce a 8-bit characters stream using OEM code-page.
As charset depends on OS config (ex: CP437 [OEM-US/latin-US], CP850 [OEM 850/latin-1]),
before being returned, output is converted to a wide-char string with function OEMtoUNICODE.
Resulting buffer is allocated with LocalAlloc.
It is the caller's responsibility to free the memory used by the argument list when it is no longer needed.
To free the memory, use a single call to LocalFree function.
*/
LPWSTR DosExec(LPWSTR command){
// Allocate 1Mo to store the output (final buffer will be sized to actual output)
// If output exceeds that size, it will be truncated
const SIZE_T RESULT_SIZE = sizeof(char)*1024*1024;
char* output = (char*) LocalAlloc(LPTR, RESULT_SIZE);
HANDLE readPipe, writePipe;
SECURITY_ATTRIBUTES security;
STARTUPINFOA start;
PROCESS_INFORMATION processInfo;
security.nLength = sizeof(SECURITY_ATTRIBUTES);
security.bInheritHandle = true;
security.lpSecurityDescriptor = NULL;
if ( CreatePipe(
&readPipe, // address of variable for read handle
&writePipe, // address of variable for write handle
&security, // pointer to security attributes
0 // number of bytes reserved for pipe
) ){
GetStartupInfoA(&start);
start.hStdOutput = writePipe;
start.hStdError = writePipe;
start.hStdInput = readPipe;
start.dwFlags = STARTF_USESTDHANDLES + STARTF_USESHOWWINDOW;
start.wShowWindow = SW_HIDE;
// We have to start the DOS app the same way cmd.exe does (using the current Win32 ANSI code-page).
// So, we use the "ANSI" version of createProcess, to be able to pass a LPSTR (single/multi-byte character string)
// instead of a LPWSTR (wide-character string) and we use the UNICODEtoANSI function to convert the given command
if (CreateProcessA(NULL, // pointer to name of executable module
UNICODEtoANSI(command), // pointer to command line string
&security, // pointer to process security attributes
&security, // pointer to thread security attributes
TRUE, // handle inheritance flag
NORMAL_PRIORITY_CLASS, // creation flags
NULL, // pointer to new environment block
NULL, // pointer to current directory name
&start, // pointer to STARTUPINFO
&processInfo // pointer to PROCESS_INFORMATION
)){
// wait for the child process to start
for(UINT state = WAIT_TIMEOUT; state == WAIT_TIMEOUT; state = WaitForSingleObject(processInfo.hProcess, 100) );
DWORD bytesRead = 0, count = 0;
const int BUFF_SIZE = 1024;
char* buffer = (char*) malloc(sizeof(char)*BUFF_SIZE+1);
strcpy(output, "");
do {
DWORD dwAvail = 0;
if (!PeekNamedPipe(readPipe, NULL, 0, NULL, &dwAvail, NULL)) {
// error, the child process might have ended
break;
}
if (!dwAvail) {
// no data available in the pipe
break;
}
ReadFile(readPipe, buffer, BUFF_SIZE, &bytesRead, NULL);
buffer[bytesRead] = '\0';
if((count+bytesRead) > RESULT_SIZE) break;
strcat(output, buffer);
count += bytesRead;
} while (bytesRead >= BUFF_SIZE);
free(buffer);
}
}
CloseHandle(processInfo.hThread);
CloseHandle(processInfo.hProcess);
CloseHandle(writePipe);
CloseHandle(readPipe);
// convert result buffer to a wide-character string
LPWSTR result = OEMtoUNICODE(output);
LocalFree(output);
return result;
}
我在github上有一个类似的程序[windows7和10测试]
https://github.com/vlsireddy/remwin/tree/master/remwin
这是服务器程序
- 在Windows的UDP端口(5555)上侦听名为“Local Area Connection”的接口并接收udp数据包。
- 收到的udp数据包内容在cmd.exe上执行[请不要在运行命令后关闭cmd.exe并且输出字符串[执行的命令的输出]通过相同的udp端口反馈到客户端程序]。
- 换一种说法,
在udp数据包中收到的命令 - >解析的udp数据包 - >在cmd.exe上执行 - >输出在同一端口上发送回客户端程序
这不会显示“控制台窗口”
无需人员在cmd.exe上手动执行命令
remwin.exe可以在后台运行,也可以是瘦服务器程序