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).
How can I get the exit code from the following PowerShell command?: Start - Process - FilePath "C:WindowsSystem32robocopy.exe" - ArgumentList "C:Bogus Folder", "C:Target", / MIR - Wait. The above example should return an exit code of 16. Tuesday, November 9, 2010 1:35 AM.
We need this command because it gives us various ways to open the process and see them. Following are the powershell start-process are: In the below example we are inside the ranjan1 folder and we want to open a file with name test2.txt in any default editor. It started the process by opening the file.
This example starts PowerShell by using the Run as administrator option. This example shows how to find the verbs that can be used when starting a process. The available verbs are determined by the filename extension of the file that runs in the process.
"0xC0000142" or "-1073741502" Stop error when many PowerShell scripts call the Console.Write method or when you try to start many console applications on a PowerShell console in Windows 7 or in Windows Server 2008 R2 More...
start-process
is an 'alias' for System.Diagnostics.Process.Start()
, so yes, it does make use of CreateProcessWithLogonW()
. 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.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With