Controlling a Service on a workgroup server using Remote PowerShell and a Non-Privileged account

A few weeks ago I was working on a distributed application where some components where running on a workgroup joined DMZ server. The application was misbehaving and a PowerShell script had been written to restart the services on the main server, problem was that restarting the services on the main server also required a service on the DMZ server to be restarted.

Given the script on the main server was written in PowerShell we decided to use remote PowerShell to restart the service on the workgroup server in the DMZ, this turned out to be more complex than I had anticipated. Having never used remote PowerShell with servers in a workgroup we assumed it would work the same was as with domain joined systems…..this is not the case.

First thing you need is to download ‘subinacl’ from, the tool is a little old but it still works on 2008 R2.

To give the local non-privileged account on the DMZ server rights to control the service in question use subinacl from an admin command prompt and run the following command

subinacl /service MYSERVICE /grant=localhost\MYUSER=QSTO

This gives the non admin account MYUSER rights to start and stop the service MYSERVICE


Next enable PSRemoting on the DMZ server



The PSRemoting command enables the Windows Remote Management interface on all interfaces so to lock this down we use the following commands to delete the listeners PSRemoting creates and then add a listener on our management interface only

Remove-WSManInstance winrm/config/Listener -SelectorSet @{Address="*";Transport="http"}
Remove-WSManInstance winrm/config/Listener -SelectorSet @{Address="*";Transport="https"}
New-WSManInstance winrm/config/Listener -SelectorSet @{Address="IP:";Transport="http"}

For my purpose running the remote PowerShell over http was OK but a more secure method would be to only use https as a transport


The next step is to give the non-privileged account rights to remote PowerShell in to the server…by default only Admin accounts can use remote PowerShell.

Set-PSSessionConfiguration –Name Microsoft.Powershell –ShowSecurityDescriptorUI

This command will pop up a security dialog box where you can select the local account, in this case MYUSER. I found that I only needed to give the user Read and Execute rights to be able to restart the service.


The following commands can be used to check that WSMan is listening on the right interface and that the user now has access to use remote PowerShell

dir wsman:\localhost\Listener
Get-PSSessionConfiguration –Name Microsoft.Powershell | fl


There is another remote PowerShell difference when servers are in a workgroup, each server you want to initiate a remote PowerShell session from needs to be authorised on the destination using the following command

Set-item wsman:localhost\client\trustedhosts -value


As I have used http as the transport you need to run a similar command on the source server (note that if using https you do not need to preform this step)

Set-item wsman:localhost\client\trustedhosts -value


From the remote server you should now be able to initiate a remote PowerShell connection to the workgroup server using -Credential this allows you to enter the password for the local user MYUSER

Enter-PSSession -Credential MYUSER


Ok so the last piece is how to pass the -credentials to the our remote PowerShell session with out a pop up box coming up. There are quite a few blogs that cover this but the basic commands are as follows.

# These commands prompt for the password to be entered and then store it securely in the file specified.
#Note: only the user this command is run under can decrypt the password so you if you are going to call this from another script make sure you run this code as that user
$MyCred = Get-Credential
$MyCred.Password | ConvertFrom-SecureString | Set-Content FILENAME

#This is how you read the file back in and create a credential object
$MyPass = Get-Content FILENAME | ConvertTo-SecureString
$MyCred = New-Object System.Management.Automation.PsCredential(MYUSER,$MyPass)


So putting the above with a remote PowerShell session we get the following code

$MyPass = Get-Content FILENAME | ConvertTo-SecureString
$MyUser = "MYUSER"
$MyCred = New-Object System.Management.Automation.PsCredential($MYUSER,$MyPass)
Invoke-Command -ScriptBlock {Get-Process} -ComputerName -Credential $MyCred

Innovation Lead at Datacom NZ by day and MS Azure geek at night.  I also help run the Microsoft Wellington Infrastructure and Azure User group.