I have been writing a few powershell scripts for administrative purposes lately and I thought it would be useful if I could run these scripts from a web page.
You could of course re-write the PowerShell scripts in C# or VB.Net, but I think it's quite useful to have a single script, that you can either run from the commandline, or through a web page.
The following example aspx shows how to read a script from file, pass parameters to the script and then run the script, echoing the output from the script to the web page.
To use this you will need:
- This aspx in the root of a web application (see below)
- A web.config for the ASP.Net config (see below)
- If you're application is running in an application pool using Network Service, that context will need read-access to the root of the virtual directory
- A powerShell script (or just paste some script to the textbox)
- System.Management.Automation in the .\bin directory of the web application
I even tested a PowerShell script that compiles dynamic VB.Net code and calls an API through PInvoke inside the VB.Net, and that PS1 script worked fine.
Note the use of "Out-String" to return the output in string format. I did try and use pipeline.Output, but that didn't return anything when the PS1 was calling write-output. Also, the parameter passing uses $args, as I couldn't get Params() to work as it does when at the top of a PS1 script.
--
Example web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.net>
<defaultProxy enabled="false"/>
</system.net>
<system.web>
<pages validateRequest="false"/>
<compilation defaultLanguage="c#" debug="false"/>
<customErrors mode="Off"/>
<authentication mode="Windows"/>
<identity impersonate="true"/>
</system.web>
</configuration>
--
Example test.ps1:
if ($args.count -ge 2)
{ $text = $args[1]}
write-output $text
--
Example Test.aspx
<%@ Page language="c#" AutoEventWireup="true" Debug="true" %>
<%@ Import Namespace="System" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Management.Automation.Runspaces" %>
<%@ Import Namespace="System.Management.Automation" %>
<%@ Import Namespace="System.Collections.ObjectModel" %>
<script language="C#" runat="server">
// The previous lines use <%...%> to indicate script code, and they specify the namespaces to import. As mentioned earlier, the assemblies must be located in the \Bin subdirectory of the application's starting point.
// http://msdn.microsoft.com/en-us/library/aa309354(VS.71).aspx
private void Button3_Click(object sender, System.EventArgs e)
{
String fp = Server.MapPath(".") + "\\" + tPowerShellScriptName.Text;
StreamReader sr = new StreamReader(fp);
tPowerShellScriptCode.Text = sr.ReadToEnd();
sr.Close();
}
private void Button2_Click(object sender, System.EventArgs e)
{
tPowerShellScriptResult.Text = RunScript(tPowerShellScriptCode.Text);
}
// http://msdn.microsoft.com/en-us/library/ms714635(VS.85).aspx
private string RunScript(string scriptText)
{
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
// Create a new runspaces.command object of type script
Command cmdScript = new Command(scriptText, true, false);
cmdScript.Parameters.Add("-t", txtInput.Text);
pipeline.Commands.Add(cmdScript);
//You could also use: pipeline.Commands.AddScript(scriptText);
// Re-format all output to strings
pipeline.Commands.Add("Out-String");
// Invoke the pipeline
Collection<PSObject> results = pipeline.Invoke();
//String sresults = pipeline.Output.Count.ToString();
//sresults = sresults + "," + results.Count.ToString();
String sresults = "";
foreach (PSObject obj in results)
{
sresults = sresults + obj.ToString();
}
// close the runspace and set to null
runspace.Close();
runspace = null;
return sresults;
}
</script>
<form id="Form1" method="post" runat="server">
<P> <asp:Label id="Label1" runat="server" Width="104px">Parameter:</asp:Label>
<asp:TextBox id="txtInput" runat="server"></asp:TextBox></P>
<P> <asp:Button id="Button3" runat="server" Text="Load" OnClick="Button3_Click"></asp:Button> </P>
<P> <asp:Button id="Button2" runat="server" Text="Run" OnClick="Button2_Click"></asp:Button> </P>
<P> <asp:Label id="Label2" runat="server" >Relative script name:</asp:Label>
<asp:TextBox id="tPowerShellScriptName" Text="test.ps1" runat="server"></asp:TextBox></P>
<P> <asp:TextBox rows="20" columns="120" TextMode="multiline" id="tPowerShellScriptCode" runat="server"></asp:TextBox></P>
<P> <asp:TextBox rows="8" columns="120" TextMode="multiline" id="tPowerShellScriptResult" runat="server"></asp:TextBox></P>
</form>
Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.
No comments:
Post a Comment