Windows下C++隐藏启动命令行及读取日志文件的问题
问题分析与解决方案
核心原因
你遇到的问题不是权限问题,而是工作目录不匹配:
当调用ShellExecute时第5个参数传了NULL,子进程(cmd.exe)会使用系统默认工作目录(通常是C:\Windows\System32),所以abc.log被写入到了这个系统目录下,而你的检测代码是在当前程序的运行目录查找文件,自然找不到。
解决方法
方法1:指定ShellExecute的工作目录
获取当前程序的运行目录,传递给ShellExecute的第5个参数,让cmd在你的程序目录下生成日志文件:
// 获取当前程序的运行目录 WCHAR szPath[MAX_PATH]; GetModuleFileNameW(NULL, szPath, MAX_PATH); PathRemoveFileSpecW(szPath); // 去掉文件名,保留目录 std::wstring torun = L"/c abc.exe >abc.log"; HINSTANCE retVal = ShellExecuteW(NULL, L"open", L"cmd", torun.c_str(), szPath, SW_HIDE);
方法2:使用绝对路径指定日志文件位置
直接在命令行里指定abc.log的绝对路径,确保写入位置和检测位置一致:
// 获取当前程序的运行目录 WCHAR szPath[MAX_PATH]; GetModuleFileNameW(NULL, szPath, MAX_PATH); PathRemoveFileSpecW(szPath); std::wstring logPath = std::wstring(szPath) + L"\\abc.log"; std::wstring torun = L"/c abc.exe >" + logPath; HINSTANCE retVal = ShellExecuteW(NULL, L"open", L"cmd", torun.c_str(), NULL, SW_HIDE); // 检测时直接使用该绝对路径,或保持原有检测代码(日志已在当前目录)
额外建议:优先使用CreateProcess(更可控)
如果需要更精细的进程控制,推荐用CreateProcess代替ShellExecute,它能更明确地控制工作目录、输出重定向等,避免路径类问题:
STARTUPINFOW si = { sizeof(si) }; PROCESS_INFORMATION pi; si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; // 隐藏窗口 // 构建带绝对日志路径的命令行 WCHAR szPath[MAX_PATH]; GetModuleFileNameW(NULL, szPath, MAX_PATH); PathRemoveFileSpecW(szPath); std::wstring cmdLine = L"cmd /c abc.exe >" + std::wstring(szPath) + L"\\abc.log"; BOOL success = CreateProcessW(NULL, &cmdLine[0], NULL, NULL, FALSE, 0, NULL, szPath, &si, &pi); if (success) { CloseHandle(pi.hProcess); CloseHandle(pi.hThread); }
验证方式
修改前可先去C:\Windows\System32目录查看是否存在生成的abc.log,确认问题根源;修改代码后,日志文件会出现在程序运行目录下,原有检测代码即可正常识别文件。
内容的提问来源于stack exchange,提问作者John Smith
相关产品推荐
相关产品推荐

