【问题标题】:How to add process arguments using CreateProcessAsUserA如何使用 CreateProcessAsUserA 添加流程参数
【发布时间】:2020-08-13 20:14:56
【问题描述】:

我从这里想出了如何使用CreateProcessAsUserA() 打开一个进程:

example code: A service calls CreateProcessAsUser() I want the process to run in the user's session, not session 0

现在,我需要添加进程参数以正确运行程序,我的意思是像 -steam 这样的参数。

我在 Google 上找不到任何解决方案。请帮帮我。

【问题讨论】:

  • 这是 C 题还是 C++ 题。不要使用您不使用的语言进行标记。删除了c。如果更合适,请将c++ 替换为c
  • @ikegami:问题是关于 API 的。只要语言有绑定,具体的就无关紧要了。问题或其答案与调用者使用的是 C 还是 C++ 无关。

标签: c++ process


【解决方案1】:

API is defined 是这样的:

BOOL CreateProcessAsUserA(
  HANDLE                hToken,
  LPCSTR                lpApplicationName,
  LPSTR                 lpCommandLine,
  LPSECURITY_ATTRIBUTES lpProcessAttributes,
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
  BOOL                  bInheritHandles,
  DWORD                 dwCreationFlags,
  LPVOID                lpEnvironment,
  LPCSTR                lpCurrentDirectory,
  LPSTARTUPINFOA        lpStartupInfo,
  LPPROCESS_INFORMATION lpProcessInformation
);

您可以将命令行添加到目标 EXE 的末尾。

因此,使用上面的示例,它看起来像这样:

rc = CreateProcessAsUserA(hUserToken,               // user token
                       0,                           // app name
                       (LPSTR)"c:\\foo.exe -steam", // command line
                       0,                           // process attributes
                       0,                           // thread attributes
                       FALSE,                       // don't inherit handles
                       DETACHED_PROCESS,            // flags
                       0,                           // environment block
                       0,                           // current dir
                       &si,                         // startup info
                       &pi);

对于lpCommandLine,此方法的“A”版本不需要是非常量,而“W”版本则需要。

如果可执行文件的路径中有空格,您需要用引号将其括起来:

(LPSTR)"\"c:\\my files\\foo.exe\" -steam"

预计到达时间:

对于如何为目标程序生成命令行存在一些困惑。为了保持 C 风格(argv[0] 是目标可执行文件的路径),你不应该使用 lpApplication 参数,如果你这样做了,你仍然希望 lpCommandLine 看起来像上面那样。

来自文档的信息:

如果lpApplicationNamelpCommandLine 都不是NULL,则*lpApplicationName 指定要执行的模块,*lpCommandLine 指定命令行。新进程可以使用GetCommandLine 检索整个命令行。用 C 编写的控制台进程可以使用 argcargv 参数来解析命令行。因为argv[0]是模块名,所以C程序员一般会重复模块名作为命令行的第一个记号。

【讨论】:

【解决方案2】:

如果您发现正确引用引号很棘手,您可以创建一个函数来做到这一点。

C++17:

#include <initializer_list>
#include <string_view>
#include <utility>

// A function to prepare a commandline for execution by quoting
auto prep_cmd(std::initializer_list<std::string_view> args) {
    if(args.size()==0) throw std::runtime_error("No command, no fun");

    auto it = args.begin();

    std::string AppName(*it);                 // AppName is returned unchanged
    std::string CmdLine('"' + AppName + '"'); // but quoted when used in the commandline

    for(++it; it != args.end(); ++it) {
        CmdLine += ' ' + std::string(*it);            // add argument unquoted
        // CmdLine += " \"" + std::string(*it) + '"'; // or quote the argument too
    }
    return std::pair{AppName, CmdLine};               // return the result
}

然后调用它:

auto[AppName, CmdLine] = prep_cmd({
    R"aw(C:\Program Files (x86)\Steam\steamapps\common\Counter-Strike Global Offensive\csgo.exe)aw",
    "-steam"
});

使用结果:

    CreateProcessAsUserA(
        hToken,
        AppName.c_str(),   // const char*
        CmdLine.data(),    // char*
        ...
    );

【讨论】:

  • @Hirchance 这很奇怪。你打印出这两个字符串来检查错误了吗?
  • @Hitchance 那是ERROR_INVALID_HANDLE。在调用CreateProcessAsUserA 之前,您需要检查您是否从LogonUserDuplicateTokenEx 获得了有效句柄。 prep_cmd 返回的字符串看起来正确吗?你能把它们作为评论粘贴在这里吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-16
  • 1970-01-01
相关资源
最近更新 更多