I'm running into a strange behavior with a powershell Start-Process call.
Here is the call:
$process = start-process `
"C:\somepath\MyBinary.exe" `
-PassThru `
-Credential $defaultCredential `
-Wait `
-WorkingDirectory "C:\somepath" `
-LoadUserProfile
if ($process.ExitCode -ne 0)
{
#do something
}
This call always return with the exit code -1073741502
.
After a quick search, this exit code seems related to a generic error when the program could not load its required dll (aka. STATUS_DLL_INIT_FAILED
).
When I run it without -Credential $credential
the program runs correctly.
In order to isolate the problem, I manually launched some.exe
in a prompt with my target credential and it runs smoothly.
So the problem only seems to come from the way the start-process cmdlet effectively launch the process.
I found some potential solutions for this problem I tried to apply with no luck : link and link.
Would you have any idea of what's going on here ?
Edit 1:
I run a proc mon for monitoring program activities when launched directly or via the powershell script. The problem seems to occur when loading kernelbase.dll
.
Local procmon dump (working):
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 (failing, see thread exit, and process exit code -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
Edit 2:
I should mention the powershell script is run from a service (it's a bamboo service agent). And i just found this thread saying:
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).
My guess is that powershell start-process call is making uses of CreateProcessWithLogonW
...
Edit 3:
My service is run with a custom user (because I cannot impersonate from System), so as read 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
is an 'alias' forSystem.Diagnostics.Process.Start()
, so yes, it does make use ofCreateProcessWithLogonW()
. As noted, this method can't be called from a service process, it can only be called from an 'interactive' process. The caveat to that "only" is the one you've discovered - that when you aren't changing credentials, it can at least get the process started. (This may actually even be a bug - a Microsoft Support engineer I spoke with about this issue was "surprised" it worked at all.)The only (supported) way to launch another process from inside a service process is to use the native Win32 API method
CreateProcessAsUser()
. An example of how to do this is C#.NET can be found in the answer to the question mentioned in edit #2.A Windows process must launched as part of a user session. If the launching process is running as part of an interactive session - the kind where you logged in using CTRL+ALT+DELETE and have a desktop open - then you can use
CreateProcessWithLogonW()
, which will use your current user session automatically. If the launching process is a service, or "batch" process (as Scheduled Tasks are), then the launching process must either create a new user session (or identify an existing one) to launch the new process in (which is what the code in the afore-mentioned answer does.)