So, there is this process, that if the user could click a button themselves would save a lot of stress on everyone – the person who has to run the powershell script AND the people who have to ask (who wants to pester someone all the time?)
So in prep – I did a test – I didn’t know anything about powershell scripting so I hit google. I found a simple copy/paste of a file script and modified it to copy a file from one directory to another (and it echos something to the command line). Since it is the www – I made a share location so that it could be run from the network instead of my “C:\temp” directory because C: means MY c:\ and MY will change depending on who hits the button.
Next, I went and copied and pasted an example from someone else, found out which “using” statements are required, hooked up a following DLL manually required to get this working and presto – it worked in about 1/2 hour. Here are the steps:
Steps
- make a share and a destination directory (might need a share for that too).
- Make a new web project or aspx page
- Manually connect the following powershell DLL into the project C:\Windows\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35\System.Management.Automation.dll
- make your powershell script and test it (it is included in the code below – kinda – in the variable: “st”)
- fudge your script into the code below – I already did and in the future, if this goes through I would read it from a text file not encode it like I did – this was just a test
- compile, test it and publish it (ok – I can write that easier than I did it but … it works 🙂 )
[csharp]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Management;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Text;
using System.Collections;
using System.Collections.ObjectModel;
namespace RunPowerShellToCopyDb
{
public partial class _Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void ButtonDoIt_Click(object sender, EventArgs e)
{
string st = "";
//ideally we want to read this from a file in the App_Data directory or something but this is good test.
st += "$targetdirectory = \"\\\\cdc-ebley2-7\\temp\\dest\"\n";
st += "$sourcedirectory = \"\\\\cdc-ebley2-7\\temp\"\n";
st += "if (!(Test-Path -path $targetdirectory)) {New-Item $targetdirectory -Type Directory}\n";
st += "Copy-Item -Path $sourcedirectory\\a.csv -Destination $targetdirectory\n";
st += "echo this_is_an_echo_statement_after_the_copy_is_done Look at \\\\cdc-ebley2-7\\temp\\dest for a.csv";
outputItem.InnerHtml = "output: "+RunScript(st);
}
private string RunScript(string scriptText)
{
// create Powershell runspace
Runspace runspace = RunspaceFactory.CreateRunspace();
// open it
runspace.Open();
//runspace.SessionStateProxy.SetVariable("DemoForm", this);
// create a pipeline and feed it the script text
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(scriptText);
// add an extra command to transform the script
// output objects into nicely formatted strings
// remove this line to get the actual objects
// that the script returns. For example, the script
// "Get-Process" returns a collection
// of System.Diagnostics.Process instances.
pipeline.Commands.Add("Out-String");
// execute the script
PSObject bob;
Collection<PSObject> results = pipeline.Invoke();
// close the runspace
runspace.Close();
// convert the script result into a single string
StringBuilder stringBuilder = new StringBuilder();
foreach (PSObject obj in results)
{
stringBuilder.AppendLine(obj.ToString());
}
return stringBuilder.ToString();
}
}
}
[/csharp]
[csharp]
<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="RunPowerShellToCopyDb._Default" %>
<asp:Content runat="server" ID="FeaturedContent" ContentPlaceHolderID="FeaturedContent">
<section class="featured">
<div class="content-wrapper">
<hgroup class="title">
<h1><%: Title %>.</h1>
<h2>Modify this template to jump-start your ASP.NET application.</h2>
</hgroup>
<p>
<asp:Button ID="ButtonDoIt" runat="server" Text="Jamie … Press this button" OnClick="ButtonDoIt_Click" />
</p>
</div>
</section>
</asp:Content>
<asp:Content runat="server" ID="BodyContent" ContentPlaceHolderID="MainContent">
<h3>Output:</h3>
<ol class="round">
<li id="outputItem" runat="server">
</li>
</ol>
</asp:Content>
[/csharp]