Create a Powershell Web Application

How to create a Powershell Web Application? This article will give you some guidelines on how to deploy a very simple web application that leverages Powershell and if you follow it completely, you’ll be able to have a fully functional web application.

This is a very important instrument, especially when our goal is to automate as much as possible the environment and repetitive tasks or offload a 2nd or 3rd level task to a 1st level representative. You could build a web application to check permissions for a specific shared folder (I’ve done that successfully) or you could deploy an app that would check the current top 10 RAM processes being used on a remote server (super handy to hand off to a 1st level support team who many have no access to the server) and so on.

Please see the final notes at the end of this article.

Prerequisites

You will need Visual Studio to follow this.

Creating a new Project

  • Click on File > New > Project
    • visual-studio_create-new-project
  • Select Installed > Templates > Visual C# > Web and click ASP .NET Web Application (.NET Framework). Give it a name (ITDropletsPowershell in the example).
    • visual-studio_create-new-asp.net-web-application
  • Since we want to start with a clean solution, let’s select “Empty” and click OK.
    • visual-studio_create-new-asp.net-web-application-EMPTY

Adding the needed packages to the Solution

  • Click on Tools > NuGet Package Manager > Package Manager Console
    • visual-studio-Package-Manager-Console
  • Let’s install these two packages, by running the below two lines of code:

    • This is how it’s going to look:

      visual-studio-install-packages-output

Creating the Default.aspx and the Code Behind

  • Add a New Item
    • visual-studio-add-new-item
  • Select Web Form and name it Default.aspx
    • visual-studio-new-web-form
  • Here it is:
    • visual-studio-default.aspx-brand-new

Now we have the basic to start building a web interface that will need to get our input and tweak the code behind file to let it do what we need it to do.

Web Application Example

Let’s try to build a real life example. Let’s say we want a simple form where we input a Directory (i.e. C:\Users\Username\Desktop) and the script must return us the child items.

So what we want the script to do is simply get the user to input a variable (the directory) and then call the following:

Let’s first edit the Default.aspx to look like this:

So what we changed from the original Default.aspx is:

  • Added a title “Get-ChildItem”.
  • Added an h1 Title on the page and centered “Get-ChildItem (itdroplets.com)”.
  • Added a text “Please type the directory for which you want to get the child items:” followed with a TextBox with ID Input.
  • A button with text “Run” and ID RunInput.
  • Added a text “Result” with a MultiLine TextBox with ID Result.

Time to edit the code behind. Expand Default.aspx and select Default.aspx.cs. Here’s how it’s going to look:

visual-studio-edit-code-behind

This is how my code behind looks like now, I tried adding comments so that there’s no need to repeat it below.

Let’s test this!

  • Right click on Default.aspx and select View in Browser
    • visual-studio-view-in-browser

 

Here’s our web application.

visual-studio-web-application-get-child-item

And here’s an example of the result for the folder C:\.

visual-studio-web-application-get-child-item_Test

 

Running an external Function that is stored in a Module

If you look back at the code behind above, I’ve added these lines (I removed the comments from the below):

Now those two lines will import two modules from a path under MyModuleFolder1 and MyOtherModule2. If you had a function into one of them called Sample-Function-ITDroplets, and said function would accept a parameter called “Username”, you could just called it as if you were calling Get-ChildItem!

Something like this:

You can understand that you could then go and add many other input fields in the Default.aspx page and every “variable” will be available here.

One last example

Imagine that now you want to add another parameter to the Get-ChildItem command, for instance you want to also add -Recurse. To do that, just add the following line, right under “shell.Commands.AddParameter(“Path”, Input.Text);” in the Default.aspx.cs file.

Once you run the web application again, you’ll run it in Recurse. If you’re now testing this, pay attention! If you specify a folder with a ton of files, you’ll end up waiting for quite some time!

Publishing the entire solution to an existing IIS Web Server

This is so simple and so powerful and so handy! So we’re done and we want to deploy our web application to a server we own.

  • Right click on ITDropletsPowershell and click Publish
    • visual-studio-publish
  • Select IIS, FTP, etc and then click Publish
    • visual-studio-publish-IIS-FTP-etc
  • Now add all of the info and credentials for the web-server you’re deploying this to and you’re done! Just follow the wizard through.
    • visual-studio-publish-custom-profile

Final Notes

It’s important to understand security. I will have a separated article ready soon to talk about how to secure this application we just deployed to make sure only a certain group or user can access it.

Another important factor is the ability for the account running the web application (IIS) to have access to whatever the script is doing. So the best is to run the web application with a service account and provide access to said service account. For instance, in our case with the Get-ChildItem web application, we could target a share \\itdroplets.com\myshare, but if the service account running IIS has no access to it, you’ll just get an access denied error.

I also suggest to work as much as possible on error handling, this is simple when calling external scripts as everything will be in a powershell format.

22 thoughts on “Create a Powershell Web Application

  1. Hi, thanks for your blogpost!
    I’m not sure, but I think you have to change

    this
    protected void RunInputClick(object sender, EventArgs e)

    to
    protected void ExecuteInputClick(object sender, EventArgs e)

    BR
    André

    1. You’re right 🙂 I copied/pasted from an existing application I had and forgot to update that. Thanks for spotting the error!

  2. Hi, nice post!

    I believe this line has an error:
    shell.Commands.AddParameter(“Directory”, Input.Text);

    Should be:
    shell.Commands.AddParameter(“Path”, Input.Text);

  3. Hi,

    Great tutorial for beginners (which I am).

    I have followed this but get the following error when running my web page (when searching for a directory):

    Cannot convert ‘System.String’ to the type ‘System.Management.Automation.SwitchParameter’ required by parameter ‘Directory’.

    Just searching c:\
    Any thoughts?

    1. Hi Doug,
      I think that’s because of a mistake in the code that was also pointed out by another user. I’ve updated the post, from shell.Commands.AddParameter(“Directory”, Input.Text); to shell.Commands.AddParameter(“Path”, Input.Text);. Basically that “Path” is the -Path parameter found in Get-ChildItem.

  4. Hi Simone

    May I ask you, why you dont use:
    shell.Commands.AddScript(“Get Childitem -Path” Input.Text);

    Thanks for this awesome post!

  5. Hi Simone

    I’m sorry, I’ve copied the wrong command 😉
    May I ask you why you don’t use this command?
    shell.Commands.AddScript(“Get-ChildItem -Path ” + Input.Text);

    Thanks for your answer.

    Awesome post by the way! Thanks a lot!

    1. Hey, it’s mainly to show how you could go and actually call for external scripts and adding parameters separately.
      Personally though, I prefer to run PS scripts from PHP. Note, it’s pure preference as I know a little bit of PHP (nothing special) and overall I liked the challenge to use that.

      1. Hey,
        Thank you for the quick answer!
        Is there a disadvantage when using the AddScript method as mentioned above?

        Personally, I think this would be a lot easier to code when using commands with multiple parameters e.g.
        New-ADUser -Name “ChewDavid” -Type iNetOrgPerson -Path “DC=AppNC” -Server xyz etc

        Or, do I misunderstand something?

        Thanks for your answer.

  6. I am trying to get the second approach to work (running an external function stored in a module). The function is called “Invoke-script”. Each time I run it from my aspx page I get an error saying : The term ‘. Invoke-script’ is not recognized as the name of a cmdlet, function, script file, or operable program. I can get the first example to work, the one using Get-ChildItem.

    Any help would be greatly appreciated.

    Barry

    1. Hi Barry,
      So you’re importing your invoke-script function by using iss.ImportPSModulesFromPath("C:\\Scripts\\InvokeScript")? Remember that this imports a module based on its path and it looks like it’s not loading it correctly.
      Try naming the container folder for the module the same as the module itself. For example, if your module is called InvokeScript.psm1, the store it in C:\\Your\\Path\\InvokeScript and call it with iss.ImportPSModulesFromPath("C:\\Your\\Path\\InvokeScript"). Of course, also make sure the IIS process has rights to that location.

    1. Hi, you can do it at the powershell level if you like. For instance, if you’re writing the output as it is from PS, then you could just convert-tohtml in PS and return that.

  7. Hi,
    first of all thanks for the awesome blog. Here is what I did:
    I followed the steps and completed the project then I uploaded it in the Azure cloud 😉
    guess what?? I am NOT getting the result as the code was excuted on my local machine! Instead I get a different result because the code is obviously excuted on the azure cloud! here is how the result looks like:

    Applications
    Config
    Dumps
    DWASFiles
    inetpub
    Logs
    OPC_Workaround_temp
    Resources
    RolePatcher

    I also tried some modifications and replaced the command Get-Childitem with Get-Process and experemented the same difference in results.

    My question is: how can I keep having my app in the cloud while getting the result as the code excuted locally on my PC? any ideas

    thanks again!
    Jay

    1. Hi Jay,

      That’s expected. The code here is executing at the server end. To be honest, I don’t think this is possible, I think the browsers will try and deny any interaction outside of the browser itself. I’m not a super expert there.
      However, the only workaround I can think of, is if you were using this web server in your domain environment. So if this Azure VM has access to the local infrastructure, you could try manually passing the machine name and then change the command to Invoke-Command..

  8. Is knowledge of C# required to build such web applications? I see some commands used which are generally not used in powershell?

    1. Hi Sam, yes and no.. It depends on how complex you want to build the web end. If you could have your PS script to handle all of the work, then you could just use this example to send variables to your PS script and then output whatever your script is returning. If you’re looking for something that, in my opinion, is a bit simpler, check this out: https://www.itdroplets.com/run-a-powershell-script-from-php/.
      It can run from IIS and to me PHP is a bit easier to work with.

Leave a Reply

Your email address will not be published. Required fields are marked *