【问题标题】:CreateProcess - lpApplicationName vs lpCommandLineCreateProcess - lpApplicationName vs lpCommandLine
【发布时间】:2011-04-18 15:40:48
【问题描述】:

我一直在使用 CreateProcess Win API,我想知道使用 lpApplicationName 和 lpCommandLine 作为参数与使用 lpCommandLine 有什么区别。只是 lpCommandLine 参数。

例如:

CreateProcess(NULL, L"C:\Path\To\Notepad.exe", L"C:\Path\To\File\To\Load.txt"... etc
CreateProcess(NULL, NULL, L"C:\Path\To\Notepad.exe C:\Path\To\File\To\Load.txt"... etc

我假设仅使用 lpCommandLine 的第二个选项就像打开 cmd.exe 并运行该行。但是第一行呢,它是在加载应用程序并以不同的方式指定命令行参数吗?

我查看了 API 的 MSDN 文档,但它似乎并没有真正详细说明正在发生的事情,即参数可以包含的内容,这很好,但我只是对我应该做什么感到困惑当有多种方法可以做到时。

请注意,我知道这两个示例行可能不起作用,因为 lpCommandLine 需要 LPTSTR,而不是 LPCTSTR。只是为了便于理解。

非常感谢您的帮助!

安迪

【问题讨论】:

  • 是什么让你说 MSDN 没有详细解释发生了什么?它几乎不能更详细。简而言之,lpApplicationName 或多或少完全符合您的要求,仅此而已,而 lpCommandLine 增加了很多解释和魔法(附加扩展、搜索 PATH 等)。而且,正如约翰所说,通常最好的方法是同时使用两者。
  • 好吧,也许有一些细节我第一次没看懂/错过了,但我还是觉得有点模棱两可。

标签: c++ winapi parameters process


【解决方案1】:

推荐的方法是同时使用这两个参数。如果您不指定 lpApplicationName,您让 Windows 解析 lpCommandLine 以找出应用程序名称。因为空格是文件名和目录名中的有效字符,这可能(在极少数情况下)导致运行错误的应用程序。 (例如,如果您有 c:\program.exe,并且您在 Windows XP 中的 c:\program 文件下启动程序)。

在这两种情况下,您都应该在 lpCommandLine 中使用应用程序名称,因为它用于计算 Argv[0]。

【讨论】:

  • 推荐的方式是仅使用命令行,并为 lpApplicationName 参数传递NULL。如果应用程序名称包含空格,则需要引用它。如果您需要将非标准命令行(不包含可执行映像的路径名作为第一个参数)传递给正在创建的进程,请仅使用这两个参数。
  • @IInspectable,您的建议基于什么?在“安全备注”下阅读 CreateProcess 的 MSDN 页面,然后描述了该问题……“为避免此问题,请不要为 lpApplicationName 传递 NULL。如果确实为 lpApplicationName 传递 NULL……”。所以微软建议不要传递 NULL,但如果你这样做,那么使用引号。
  • 建议基于逻辑推理。大多数应用程序期望启动进程的可执行映像作为第一个参数 (argv[0])。对于这些情况,传递 lpCommandLine 就足够了,并且可以防止生成重复的冗余信息。同时传递 lpApplicationNamelpCommandLine 允许构造一个命令行,它不包含可执行映像作为其第一个参数。它应该用于那些极少数情况下,即应用程序需要一个(非标准)命令行,该命令行没有可执行映像作为其第一个参数。
  • 如果您使用lpApplicationName,那么系统将不会使用PATH 环境变量来定位可执行文件,这可能不是您想要的。所以我必须第二次@IInspectable 关于使用lpCommandLine,并将正确引用的路径作为首选选项。仅当您要启动的确切可执行文件的绝对路径已知时,您才应使用 lpApplicationName
【解决方案2】:

我从不使用 lpApplicationName 并且总是引用 lpCommandLine 的应用程序部分,在您的示例中,我将执行 "C:\Path\To\Notepad.exe" "C:\Path\To\File\To\Load.txt"(引用传递给 CreateProcess 的所有路径是一个好主意)仅使用 lpApplicationName 可能会导致访问 argv 的子进程出现问题 [ 0] 这就是我远离它的原因。


<rant> 在您自己以外的任何东西上使用 CreateProcess 可能会出现问题,因为 NT6+ 可以在任何时候决定您正在执行的事情需要管理员权限,因为应用程序兼容性垫片和/或安装程序检测然后 CreateProcess 就会失败。除非您需要使用调试或脱离作业标志,否则我建议您调用 ShellExecute[Ex] 以确保安全...</rant>

【讨论】:

  • 你关于使用 ShellExecute 的最后一点很有趣,这就是我们最初使用的,但我们不得不转移到 createprocess 因为 Adob​​e Reader 需要指定当前用户的环境块(所以它看起来在用户文件文件夹而不是系统配置文件),我认为你不能用 ShellExecute 做到这一点。如果我们使用 shell 执行并且 Adob​​e Reader 是默认处理程序,它会加载,但会崩溃,因为它拒绝访问 systemprofile 文件夹。有什么建议么? :)
  • @Andy:这是一个咆哮。不要当真。真正的问题是执行随机字符串,例如从注册表中,不知道他们指向什么。如果您不知道自己在执行什么,那么可以,您可以尝试启动安装程序。至于启动 Adob​​e Reader,ShellExecute 是一个明显的例子。不要试图猜测我用作 PDF 阅读器的用途。我没有使用 Adob​​e,部分原因是它有问题。
【解决方案3】:

According to MSDN, lpApplicationName 是可选的,可以为 NULL。在这种情况下,模块名称必须是 lpCommandLine 字符串中第一个以空格分隔的标记。

如果可执行模块是 16 位应用程序,lpApplicationName 应为 NULL,lpCommandLine 指向的字符串应指定可执行模块及其参数。

【讨论】:

    猜你喜欢
    • 2015-09-10
    • 2011-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多