New-Service -Name "MyWindowsService" -BinaryPathName "C:\SomePath\1.0.1\MyWindowsService.exe"
When running this in a PowerShell terminal, it will generate the following output which as documented is an object representing the new service:Status Name DisplayName
------ ---- -----------
Stopped MyWindowsService MyWindowsService
This is actually helpful output for a human, and maybe even for logging, bu when running this same command in C# via a PowerShell instance, the command will technically work, but you'll get the following cryptic error:
"The following exception occurred while retrieving the string: ""Exception calling ""ToString"" with ""0"" argument(s): ""There is no Runspace available to run scripts in this thread. You can provide one in the DefaultRunspace property of the System.Management.Automation.Runspaces.Runspace type. The script block you attempted to invoke was: $this.ServiceName""""", System.Object,System.ServiceProcess.ServiceController,System.WeakReference`1[System.Management.Automation.Runspaces.TypeTable], System.Management.Automation.PSObject+AdapterSet,None,System.Management.Automation.DotNetAdapter,"",System.Management.Automation.PSObject+AdapterSet, System.ServiceProcess.ServiceController,System.ServiceProcess.ServiceController,"PSStandardMembers {DefaultDisplayPropertySet}",False,False,False,False,False, "","",NoneOK not very helpful. It took a while but I deduced the output from the New-Service cmdlet was causing this issue. There are 2 ways I found to handle this.
- Suppress the Output: Since this is running in C# without human intervention, pipe in the option to suppress the output if you are not logging it or using it for some meaningful purpose. Remember, you can still get the status by using Get-Service to inspect the newly installed service, as opposed to reading the output. Use the updated command to accomplish this:
New-Service -Name "MyWindowsService" -BinaryPathName "C:\SomePath\1.0.1\MyWindowsService.exe" | out-null
- Return the Output to a Variable: The other option is simply to return the output of the cmdlet typically for use to inspect. This could be done with the following updated statement:
Keep in mind he return value is of type System.ServiceProcess.ServiceController, so you can use that as needed.$newServiceResult = New-Service -Name "MyWindowsService" -BinaryPathName "C:\SomePath\1.0.1\MyWindowsService.exe"
For my needs I prefer option #1, as I don't need to inspect the return of New-Service and as mentioned can use Get-Service to further inspect any Windows Service status at this point. With either method though you will no longer get the cryptic error as previously shown.