【问题标题】:CreateProcessW not honoring commandline [duplicate]CreateProcessW不尊重命令行[重复]
【发布时间】:2015-01-27 17:46:29
【问题描述】:

我正在尝试在 dll 中实现 CreateProcessW,以便用户可以在单独的进程中启动应用程序。

对于初学者,我在代码中对命令进行硬编码,直到我弄明白为止..

我有

STARTUPINFO si = {sizeof(STARTUPINFO), 0};
si.cb = sizeof(si);
PROCESS_INFORMATION pi = {0};
LPCTSTR AppName=L"c:\\utilities\\depends.exe";
LPTSTR Command = L"c:\\utilities\\tee.exe";
if (CreateProcessW(AppName, Command, 0, 0, 0, CREATE_DEFAULT_ERROR_MODE, 0, 0, &si, &pi)) {
        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
        return GX_RESULT_OK;
    } else {
        .. show error msg
    }

这将启动 Depends 但不会打开 Tee.exe。没有错误,它只是忽略了命令行参数。参数是正确的,我可以在运行提示符下运行它,它工作正常。如果我将 AppName 留空并将 Depends.exe 指定为 Command 参数,它也可以工作,但如果我指定了

LPTSTR Command = L"c:\\utilities\\depends.exe c:\\utilities\\tee.exe";

我得到错误 3:“系统找不到指定的路径”。

另外,通过指定 lpCurrentDirectory 参数,它同样会被忽略。

【问题讨论】:

  • 我的水晶球说你混淆了你的代码,真正的路径不是 c:\utilities。但是路径名中有空格。这需要您在路径周围加上双引号,这样它就不会被解析为多个命令行参数。
  • @HansPassant 抱歉,您的球已经起雾了!我特意选择了一条没有空格的路径来消除这个潜在的问题。
  • @Mgetz 这是不正确的。来自 MSDN:如果 lpApplicationName 和 lpCommandLine 都不是 NULL,则 lpApplicationName 指向的空终止字符串指定要执行的模块,lpCommandLine 指向的空终止字符串指定命令行。新进程可以使用 GetCommandLine 来检索整个命令行。用 C 编写的控制台进程可以使用 argc 和 argv 参数来解析命令行。因为 argv[0] 是模块名,所以 C 程序员一般会重复模块名作为命令行中的第一个标记。
  • @BenKey 就是答案——命令行字符串首先需要程序的名称,然后是第一个参数。在这种情况下,该命令似乎没有 任何 参数。
  • @marcp:不过,它是一个指针变量,它指向一个字符串文字,这在 CreateProcessW 中是不允许的。您需要改为使用 wchar_t Command[] = L"string";(或同等名称)。

标签: c++ winapi c++builder c++98


【解决方案1】:

您必须在command 中提供可执行文件

  • Appname 应该包含可执行文件的完整路径
  • Command 还应该包含 argv[0]

如果你想用记事本打开文件t.txt,你可以给出如下:

  • Appname = "c:/windows/notepad.exe";
  • command = "notepad c:/temp/t.txt";

您甚至不必提供真实的程序名称,即使是假名称也可以完成工作,因为它只是一个占位符。

像这样:command = "fake c:/temp/t.txt";

现在在 notepad.exe 中:

  • argv[0] = "notepad";
  • argv[1] = "c:/temp/t.txt";

查看完整示例:

#include <Windows.h>
#include <iostream>

using namespace std;

int main(){
    STARTUPINFO si = {sizeof(STARTUPINFO), 0};
    si.cb = sizeof(si);
    PROCESS_INFORMATION pi = {0};
    LPTSTR AppName=L"C:/Windows/notepad.exe";
    wchar_t Command[] = L"notepad C:/Temp/t.txt"; 
    DWORD res = CreateProcess(AppName, Command, 0, 0, 0, CREATE_DEFAULT_ERROR_MODE, 0, 0, &si, &pi);
    if (res) {
        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
        return 0;
    } else {
        cerr<<"error..."<<GetLastError()<<endl;
    }; 
    return 0;
}

【讨论】:

  • 第二个参数必须是可编辑内存。使用wchar_t Command[] = L"notepad C:/Temp/t.txt";
  • @DavidHeffernan,根据 MSDN (msdn.microsoft.com/en-us/library/windows/desktop/…) LPTSTR 是正确的变量类型。
  • @marcp 是的,但文字只是 LPTSTR 与 K&R C 的向后兼容性。不允许修改它们。我是第二个告诉你这个的人。粗略的网络搜索会发现无数更多的人在说同样的话。我们确实知道我们在说什么。
  • @marcp Heck,如果你愿意,不同意我的观点,但你真的认为 MSDN 搞错了。写得很大: 此函数的 Unicode 版本 CreateProcessW 可以修改此字符串的内容。因此,此参数不能是指向只读内存的指针(例如 const 变量或文字字符串)。如果此参数是一个常量字符串,该函数可能会导致访问冲突。
  • 在 Windows 中使用正斜杠也是一个坏习惯。 大多数情况下 Windows API 会为您将它们转换为反斜杠,但并非所有应用程序都接受它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-12
  • 1970-01-01
  • 1970-01-01
  • 2016-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多