【问题标题】:CreateProcessWithLogonW : unable to start processCreateProcessWithLogonW : 无法启动进程
【发布时间】:2012-11-02 16:47:16
【问题描述】:

您好,我对编程完全陌生。请有人帮助我。

我正在尝试从服务启动进程。 我需要通过提示用户输入管理员凭据来启动新进程。

我尝试使用CreateProcessWithLogonW()

我是否使用了正确的功能。 我尝试将输入用户名、密码、域作为 localhost。我为需要启动的 .exe 文件提供了完整的路径。

这是一段代码。

CreateProcessWithLogonW(L"Administrator",
                        L"localhost",
                        L"password",
                        0,
                        NULL,
                        L"c:\myupdates\myapp.exe",
                        NORMAL_PRIORITY_CLASS | CREATE_CONSOLE,
                        NULL,
                        NULL,
                        &si,
                        &pi);

Si.cb = sizeof(si);
Si.lpDesktop = L"winsta0\\default";

但这个过程从未开始。你们能告诉我我做错了什么吗? 我需要做些什么来提示用户输入管理员的凭据而不是对其进行硬编码。

【问题讨论】:

  • GetLastError() 说什么?
  • 您做错的一件事是在调用CreateProcessWithLogonW 后分配给si 结构。你应该先这样做。
  • 是我,还是正确使用 Windows API CreateProcessWithLogin() 和“我对编程完全陌生”似乎有点令人不安......
  • 在进行此调用之前,我正在分配 si 结构。此功能是否提示用户输入管理员凭据
  • 您是否检查了您正在调用的函数的documentation?它对管理员提示有什么看法?

标签: c++ windows winapi windows-7 windows-services


【解决方案1】:

CreateProcess* 函数都不会做任何提示。它们是低级 API,对 GUI 一无所知。

如果要提示用户,请使用 ShellExecuteExrunas 命令。 Windows 将首先请求提升权限,然后提示输入凭据。

【讨论】:

  • 请记住,这是在服务内部完成的,该服务在自己的桌面上运行,ShellExecuteEx() 无法在另一个桌面上运行新进程。您需要为此使用 CreateProcess...() 函数。如果您需要运行提升的进程,请尝试CreateProcessElevated()
【解决方案2】:

您可能还想正确地转义程序字符串:

L"c:\myupdates\myapp.exe"

至少应该是:

L"c:\\myupdates\\myapp.exe"

坦率地说,这段代码有很多问题,从不正确的 SI 设置到传递给 API 本身的参数。我建议您阅读更多内容。

【讨论】:

    【解决方案3】:

    一个问题是将字符串文字作为命令行参数传递,因为该参数必须是可修改的。来自CreateProcessWithLogon() 与命令行参数的关系:

    函数可以修改这个字符串的内容。因此,此参数不能是指向只读内存的指针(例如 const 变量或文字字符串)。如果此参数是一个常量字符串,该函数可能会导致访问冲突。

    您还需要转义反斜杠。改为:

    WCHAR cmdLine[] = L"c:\\myupdates\\myapp.exe"; /* 'cmdLine' is a
                                                      copy of the string
                                                      literal. */
    

    并改为传递cmdLine

    在任何 WINAPI 功能失败后检查GetLastError(),因为它会通知您失败的原因。

    【讨论】:

    【解决方案4】:

    也许现在帮助你为时已晚。但它可能对其他人有帮助。如果您使用CreateProcessWithLogonW 函数并且您正在使用Default 桌面,只需将lpDesktop 保留为NULL。

    如果lpDesktop 不是 Null,您必须在桌面和 winstation 的 DACL 中输入用户的 sid(与LookupAccountNamean 一起使用)作为ACE

    以下是为桌面添加ACE 必须执行的步骤:

    1. OpenDesktop获取桌面句柄,使用正确的dwDesiredAccess
    2. 使用GetSecurityInfoDACL_SECURITY_INFORMATION作为安全信息获取Security Descriptor
    3. 从您的Security Descriptor 获取DACL
    4. AddAccessAllowedAce添加到您用户的 sid 的 sid
    5. 将修改后的DACL 设置为您的桌面句柄

    现在对winsta0winstation 重复这些步骤

    documantaryMr. Furious 的评论帮我解决了这个问题。

    【讨论】:

      【解决方案5】:

      访问冲突归结为 lpCommandLine 参数。这意味着可编辑内存,LPWSTR 和 API 函数确实修改了缓冲区。但是你传递了一个指向不可修改内存的指针。

      但还有一个更根本的问题。您说您想提示来自服务的凭据。服务不应显示 UI,在现代版本的 Windows 中,服务根本无法显示 UI。你的设计有缺陷,你需要重新考虑。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-12-13
        • 1970-01-01
        • 2016-11-24
        • 2018-12-11
        • 2013-10-09
        • 2015-06-13
        • 1970-01-01
        相关资源
        最近更新 更多