Simple HTTP api for Executing PowerShell Scripts

PowerShell Team

[Based on the feedback, I’ve renamed this to HTTP]

There may be scenarios where you don’t need the full interactive experience of PowerShell remoting over PSRP  (PowerShell Remoting Protocol), or have the need to execute some PowerShell scripts from a non-Windows system.  You could directly code against WS-Man as I’ve blogged about a long time ago, however, it’s quite complicated requiring knowledge of SOAP and WS-Man.  In cases where you want to simply invoke a PowerShell script remotely, a REST api is a good choice since all modern programming languages make it simple to perform a HTTP GET operation.

I wrote a simple HTTP Listener in PowerShell script that uses the .Net HttpListener class.  You simply start an instance of the listener (requires an elevated prompt to listen on the network) and now you can execute an arbitrary PowerShell command-line and get back the results in a variety of formats.

Once you have the module installed (just copy the HttpListener folder to your Documents\WindowsPowerShell\Modules folder) and imported, you can start an instance by using the Start-HTTPListener commandlet:

 image

By default, I have it set to listen on port 8888 and using Integrated Windows Authentication, but this is all configurable as parameters to the commandlet.  Here, I have another PowerShell window open and I execute “get-process powershell”:

image

Note that I used the –UseDefaultCredentials to ensure I authenticate with my current security context otherwise you’ll get back Access Denied since anonymous access is not supported.

By default, I return the output as JSON.  Because the resulting JSON object is large, it’s truncated.  The body of the HTTP response is in the Content property, but it’s a byte array.  I use the Utf8 .Net class to decode it and show a portion of the JSON:

image

I can utilize the ConvertFrom-Json to make it more presentable within PowerShell:

image

Of course, if you’re using a different scripting client such as Python, Perl, or Ruby, then you would use script libraries in those languages to use the JSON version.

If you’re just playing around, you can use the Text formatting to make things more easily readable and resembles what you would get executing the same command line directly in PowerShell:

image

Other formatting options are available and if you call the HTTP endpoint without any parameters, you’ll get the basic usage information back:

image

The code is available on TechNet where I also explain a bit more on how the code actually works.

Steve Lee
Principal Test Lead PowerShell
Windows Server

2 comments

Discussion is closed. Login to edit/delete existing comments.

  • Laurentiu Leitan 0

    Hi there,
    Thank you for this script, everything runs perfect when I am running it under my user account in a powershell session, I am able to call another script in the backend with parameters and everything works like a charm.
    The problem that I have is the following, I have made the script to run as windows service under local system account in order to have the listener available at all time or after the server reboots. When I run it like this, if I run a simple script in the backend that only does a write-output, everything works ok. But when I have more complex things, like for instance converting to secure-string to read a password or when I create a new credentials ps object I always get errors like:  >ImportSecureString_InvalidArgument_CryptographicError,Microsoft.PowerShell.Commands.ConvertToSecureStringCommand in the case of the convert thing, or other errors. I guess this would be because of the way the command is executed via the $ExecutionContext.
    Do you know a way on how I could get pass this?
    Any suggestion would is appreciated.
    Many thanks, Laurentiu

    • Laurentiu Leitan 0

      Finally found the issue, it was caused by the user that has been used to create the credentials.

Feedback usabilla icon