powershell Start-Process 退出代码 -1073741502 与来自 windows 服务环境的凭据一起使用
powershell Start-Process exit code -1073741502 when used with Credential from a windows service environment
我 运行 在调用 powershell Start-Process 时遇到了一个奇怪的行为。
调用如下:
$process = start-process `
"C:\somepath\MyBinary.exe" `
-PassThru `
-Credential $defaultCredential `
-Wait `
-WorkingDirectory "C:\somepath" `
-LoadUserProfile
if ($process.ExitCode -ne 0)
{
#do something
}
此调用总是 return,退出代码为 -1073741502
。
快速搜索后,当程序无法加载其所需的 dll(又名。STATUS_DLL_INIT_FAILED
)时,此退出代码似乎与一般错误有关。
当我 运行 它没有 -Credential $credential
程序时 运行 正确。
为了隔离问题,我在提示中使用我的目标凭据手动启动了 some.exe
,它 运行 很顺利。
所以问题似乎只出在 start-process cmdlet 有效启动进程的方式上。
我找到了一些解决这个问题的潜在解决方案,我尝试申请但没有成功:link and link。
你知道这里发生了什么吗?
编辑 1:
我 运行 一个 proc mon,用于在直接启动或通过 powershell 脚本启动时监视程序活动。加载 kernelbase.dll
.
时似乎出现了问题
本地 procmon 转储(工作):
9:06:35.3837439 AM MyBinary.exe 2620 Load Image C:\Windows\SysWOW64\kernelbase.dll SUCCESS Image Base: 0x76270000, Image Size: 0x47000
9:06:35.4317417 AM MyBinary.exe 2620 RegOpenKey HKLM\System\CurrentControlSet\Control\Nls\Sorting\Versions REPARSE Desired Access: Read
9:06:35.4317751 AM MyBinary.exe 2620 RegOpenKey HKLM\System\CurrentControlSet\Control\Nls\Sorting\Versions SUCCESS Desired Access: Read
9:06:35.4318016 AM MyBinary.exe 2620 RegSetInfoKey HKLM\System\CurrentControlSet\Control\Nls\Sorting\Versions SUCCESS KeySetInformationClass: KeySetHandleTagsInformation, Length: 0
9:06:35.4318152 AM MyBinary.exe 2620 RegQueryValue HKLM\System\CurrentControlSet\Control\Nls\Sorting\Versions\(Default) SUCCESS Type: REG_SZ, Length: 36, Data: 00060101.00060101
...
Powershell procmon(失败,查看线程退出和进程退出代码 -1073741502
):
9:35:07.9455191 AM MyBinary.exe 2276 Load Image C:\Windows\SysWOW64\kernelbase.dll SUCCESS Image Base: 0x76270000, Image Size: 0x47000
9:35:07.9537146 AM MyBinary.exe 2276 Thread Exit SUCCESS Thread ID: 5112, User Time: 0.0000000, Kernel Time: 0.0000000
9:35:07.9537386 AM MyBinary.exe 2276 QueryNameInformationFile C:\Windows\System32\apisetschema.dll SUCCESS Name: \Windows\System32\apisetschema.dll
9:35:07.9537686 AM MyBinary.exe 2276 QueryNameInformationFile C:\somepath\MyBinary\MyBinary.exe SUCCESS Name: \somepath\MyBinary\MyBinary.exe
9:35:07.9537914 AM MyBinary.exe 2276 QueryNameInformationFile C:\Windows\System32\wow64cpu.dll SUCCESS Name: \Windows\System32\wow64cpu.dll
9:35:07.9538134 AM MyBinary.exe 2276 QueryNameInformationFile C:\Windows\System32\wow64win.dll SUCCESS Name: \Windows\System32\wow64win.dll
9:35:07.9538349 AM MyBinary.exe 2276 QueryNameInformationFile C:\Windows\System32\wow64.dll SUCCESS Name: \Windows\System32\wow64.dll
9:35:07.9538579 AM MyBinary.exe 2276 QueryNameInformationFile C:\Windows\System32\ntdll.dll SUCCESS Name: \Windows\System32\ntdll.dll
9:35:07.9538796 AM MyBinary.exe 2276 QueryNameInformationFile C:\Windows\SysWOW64\ntdll.dll SUCCESS Name: \Windows\SysWOW64\ntdll.dll
9:35:07.9539425 AM MyBinary.exe 2276 Process Exit SUCCESS Exit Status: -1073741502, User Time: 0.0000000 seconds, Kernel Time: 0.0000000 seconds, Private Bytes: 339,968, Peak Private Bytes: 401,408, Working Set: 1,523,712, Peak Working Set: 1,826,816
编辑 2:
我应该提到 powershell 脚本是来自服务的 运行(它是 bamboo 服务代理)。我刚刚发现这个 thread 说:
Process.Start internally calls CreateProcessWithLogonW(CPLW) when
credentials are specified. CreateProcessWithLogonW cannot be called
from a Windows Service Environment (such as an IIS WCF service). It
can only be called from an Interactive Process (an application
launched by a user who logged on via CTRL-ALT-DELETE).
我的猜测是 powershell 启动进程调用正在使用 CreateProcessWithLogonW
...
编辑 3:
我的服务是 运行 自定义用户(因为我不能从系统中模拟),所以阅读 link. I tested ensuring the "Allow service to interact with desktop" was enabled. Because it's only available for non custom accounts I set it up by hand on registry by altering HKLM\System\CurrentControlSet\Services\%myservice%
Type key (as described here and here).
start-process
是 System.Diagnostics.Process.Start()
的 'alias',所以是的,它确实使用了 CreateProcessWithLogonW()
。如前所述,此方法不能从服务进程调用,只能从 'interactive' 进程调用。 "only" 的警告是您发现的 - 当您不更改凭据时,它至少可以启动该过程。 (这实际上什至可能是一个错误 - 我与一位 Microsoft 支持工程师谈过这个问题 "surprised" 它完全有效。)
从服务进程内部启动另一个进程的唯一(受支持)方法是使用本机 Win32 API 方法 CreateProcessAsUser()
。如何做到这一点的一个例子是 C#.NET 可以在编辑 #2 中提到的问题的 the answer 中找到。
Windows 进程必须作为用户会话的一部分启动。如果启动过程 运行 作为交互式会话的一部分 - 那种您使用 CTRL+ALT+DELETE 登录并打开桌面的方式 - 那么您可以使用 CreateProcessWithLogonW()
,它将使用您当前的用户会话自动。如果启动进程是服务或 "batch" 进程(如计划任务),则启动进程必须创建一个新的用户会话(或标识现有会话)以在其中启动新进程(这是什么上述答案中的代码可以。)
目前我找到的唯一解决方案是禁用 UAC(在本地安全策略中将 EnableLUA 设置为 0 = 管理员批准模式)。所以,这肯定是一个 file/folder/registry 访问问题,UAC 在禁用时会忽略它。
有一个关于类似问题的 Microsoft KB 2701373 可用的修补程序。帮我解决了问题。
我 运行 在调用 powershell Start-Process 时遇到了一个奇怪的行为。
调用如下:
$process = start-process `
"C:\somepath\MyBinary.exe" `
-PassThru `
-Credential $defaultCredential `
-Wait `
-WorkingDirectory "C:\somepath" `
-LoadUserProfile
if ($process.ExitCode -ne 0)
{
#do something
}
此调用总是 return,退出代码为 -1073741502
。
快速搜索后,当程序无法加载其所需的 dll(又名。STATUS_DLL_INIT_FAILED
)时,此退出代码似乎与一般错误有关。
当我 运行 它没有 -Credential $credential
程序时 运行 正确。
为了隔离问题,我在提示中使用我的目标凭据手动启动了 some.exe
,它 运行 很顺利。
所以问题似乎只出在 start-process cmdlet 有效启动进程的方式上。
我找到了一些解决这个问题的潜在解决方案,我尝试申请但没有成功:link and link。
你知道这里发生了什么吗?
编辑 1:
我 运行 一个 proc mon,用于在直接启动或通过 powershell 脚本启动时监视程序活动。加载 kernelbase.dll
.
本地 procmon 转储(工作):
9:06:35.3837439 AM MyBinary.exe 2620 Load Image C:\Windows\SysWOW64\kernelbase.dll SUCCESS Image Base: 0x76270000, Image Size: 0x47000
9:06:35.4317417 AM MyBinary.exe 2620 RegOpenKey HKLM\System\CurrentControlSet\Control\Nls\Sorting\Versions REPARSE Desired Access: Read
9:06:35.4317751 AM MyBinary.exe 2620 RegOpenKey HKLM\System\CurrentControlSet\Control\Nls\Sorting\Versions SUCCESS Desired Access: Read
9:06:35.4318016 AM MyBinary.exe 2620 RegSetInfoKey HKLM\System\CurrentControlSet\Control\Nls\Sorting\Versions SUCCESS KeySetInformationClass: KeySetHandleTagsInformation, Length: 0
9:06:35.4318152 AM MyBinary.exe 2620 RegQueryValue HKLM\System\CurrentControlSet\Control\Nls\Sorting\Versions\(Default) SUCCESS Type: REG_SZ, Length: 36, Data: 00060101.00060101
...
Powershell procmon(失败,查看线程退出和进程退出代码 -1073741502
):
9:35:07.9455191 AM MyBinary.exe 2276 Load Image C:\Windows\SysWOW64\kernelbase.dll SUCCESS Image Base: 0x76270000, Image Size: 0x47000
9:35:07.9537146 AM MyBinary.exe 2276 Thread Exit SUCCESS Thread ID: 5112, User Time: 0.0000000, Kernel Time: 0.0000000
9:35:07.9537386 AM MyBinary.exe 2276 QueryNameInformationFile C:\Windows\System32\apisetschema.dll SUCCESS Name: \Windows\System32\apisetschema.dll
9:35:07.9537686 AM MyBinary.exe 2276 QueryNameInformationFile C:\somepath\MyBinary\MyBinary.exe SUCCESS Name: \somepath\MyBinary\MyBinary.exe
9:35:07.9537914 AM MyBinary.exe 2276 QueryNameInformationFile C:\Windows\System32\wow64cpu.dll SUCCESS Name: \Windows\System32\wow64cpu.dll
9:35:07.9538134 AM MyBinary.exe 2276 QueryNameInformationFile C:\Windows\System32\wow64win.dll SUCCESS Name: \Windows\System32\wow64win.dll
9:35:07.9538349 AM MyBinary.exe 2276 QueryNameInformationFile C:\Windows\System32\wow64.dll SUCCESS Name: \Windows\System32\wow64.dll
9:35:07.9538579 AM MyBinary.exe 2276 QueryNameInformationFile C:\Windows\System32\ntdll.dll SUCCESS Name: \Windows\System32\ntdll.dll
9:35:07.9538796 AM MyBinary.exe 2276 QueryNameInformationFile C:\Windows\SysWOW64\ntdll.dll SUCCESS Name: \Windows\SysWOW64\ntdll.dll
9:35:07.9539425 AM MyBinary.exe 2276 Process Exit SUCCESS Exit Status: -1073741502, User Time: 0.0000000 seconds, Kernel Time: 0.0000000 seconds, Private Bytes: 339,968, Peak Private Bytes: 401,408, Working Set: 1,523,712, Peak Working Set: 1,826,816
编辑 2:
我应该提到 powershell 脚本是来自服务的 运行(它是 bamboo 服务代理)。我刚刚发现这个 thread 说:
Process.Start internally calls CreateProcessWithLogonW(CPLW) when credentials are specified. CreateProcessWithLogonW cannot be called from a Windows Service Environment (such as an IIS WCF service). It can only be called from an Interactive Process (an application launched by a user who logged on via CTRL-ALT-DELETE).
我的猜测是 powershell 启动进程调用正在使用 CreateProcessWithLogonW
...
编辑 3:
我的服务是 运行 自定义用户(因为我不能从系统中模拟),所以阅读 link. I tested ensuring the "Allow service to interact with desktop" was enabled. Because it's only available for non custom accounts I set it up by hand on registry by altering HKLM\System\CurrentControlSet\Services\%myservice%
Type key (as described here and here).
start-process
是 System.Diagnostics.Process.Start()
的 'alias',所以是的,它确实使用了 CreateProcessWithLogonW()
。如前所述,此方法不能从服务进程调用,只能从 'interactive' 进程调用。 "only" 的警告是您发现的 - 当您不更改凭据时,它至少可以启动该过程。 (这实际上什至可能是一个错误 - 我与一位 Microsoft 支持工程师谈过这个问题 "surprised" 它完全有效。)
从服务进程内部启动另一个进程的唯一(受支持)方法是使用本机 Win32 API 方法 CreateProcessAsUser()
。如何做到这一点的一个例子是 C#.NET 可以在编辑 #2 中提到的问题的 the answer 中找到。
Windows 进程必须作为用户会话的一部分启动。如果启动过程 运行 作为交互式会话的一部分 - 那种您使用 CTRL+ALT+DELETE 登录并打开桌面的方式 - 那么您可以使用 CreateProcessWithLogonW()
,它将使用您当前的用户会话自动。如果启动进程是服务或 "batch" 进程(如计划任务),则启动进程必须创建一个新的用户会话(或标识现有会话)以在其中启动新进程(这是什么上述答案中的代码可以。)
目前我找到的唯一解决方案是禁用 UAC(在本地安全策略中将 EnableLUA 设置为 0 = 管理员批准模式)。所以,这肯定是一个 file/folder/registry 访问问题,UAC 在禁用时会忽略它。
有一个关于类似问题的 Microsoft KB 2701373 可用的修补程序。帮我解决了问题。