Friday, 30 January 2009

Execute Powershell programmatically in C#

Last week I was working on a piece of functionality where I wanted to execute powershell script programmatically. Here is the piece of code for this.

Namespaces to include:

using System.Management.Automation.Runspaces;

using System.Management.Automation;

using System.Collections.ObjectModel;

using System.Collections;

using System.Collections.Generic

This function takes following arguments

· ps1Filename – Poweshell script to excute (full file path)

· WebsiteRootPath, WebsiteURL, ServerEnvironment – these are custom arguments for my powershell (you can replace this with what arguments your ps1 is expecting)

Function:

private string ExecutePowershell( string ps1Filename, string WebsiteRootPath,string WebsiteURL,

string ServerEnvironment)

{

Runspace runspace = RunspaceFactory.CreateRunspace();

runspace.Open();

Pipeline pipeline = runspace.CreatePipeline();

//create command with script path

Command c = new Command(ps1Filename, false);

c.Parameters.Add(new CommandParameter("destinationFolder", WebsiteRootPath));

c.Parameters.Add(new CommandParameter("baseUrl", WebsiteURL));

c.Parameters.Add(new CommandParameter("env", ServerEnvironment));

pipeline.Commands.Add(c);

//create a collection to hold output of script

Collection<PSObject> results = new Collection<PSObject>();

try

{

// execute the script

results = pipeline.Invoke();

}

catch (Exception ex)

{

results.Add(new PSObject((object)ex.Message));

}

runspace.Close();

StringBuilder stringBuilder = new StringBuilder();

//loopthru all the objects returned (each object will contain output text)

foreach (PSObject obj in results)

{

stringBuilder.AppendLine(obj.ToString());

}

return stringBuilder.ToString();

}

Create webservice proxy at runtime in c#

when we add webservice reference at design time its very straigh forward to invoke the service as IDE has already created proxy for us, but when we need to programatically create a proxy for webservice at runtime, we need get the wsdl from the service and using reflection get the webmethod info and compile the proxy before we could invoke any webmethod. below is the sample code

using System;

using System.Collections.Generic;

using System.Text;

using System.Reflection;

using System.CodeDom;

using System.CodeDom.Compiler;

using System.Security.Permissions;

using System.Web.Services.Description;

namespace ConnectionLib

{

public class WSProxy

{

[SecurityPermissionAttribute(SecurityAction.Demand, Unrestricted = true)]

public static object CallWebService(string webServiceAsmxUrl, string serviceName, string methodName, object[] args)

{

System.Net.WebClient client = new System.Net.WebClient();

// Connect To the web service

System.IO.Stream stream = client.OpenRead(webServiceAsmxUrl + "?wsdl");

// Now read the WSDL file describing a service.

ServiceDescription description = ServiceDescription.Read(stream);

///// LOAD THE DOM /////////

// Initialize a service description importer.

ServiceDescriptionImporter importer = new ServiceDescriptionImporter();

importer.ProtocolName = "Soap12"; // Use SOAP 1.2.

importer.AddServiceDescription(description, null, null);

// Generate a proxy client.

importer.Style = ServiceDescriptionImportStyle.Client;

// Generate properties to represent primitive values.

importer.CodeGenerationOptions = System.Xml.Serialization.CodeGenerationOptions.GenerateProperties;

// Initialize a Code-DOM tree into which we will import the service.

CodeNamespace nmspace = new CodeNamespace();

CodeCompileUnit unit1 = new CodeCompileUnit();

unit1.Namespaces.Add(nmspace);

// Import the service into the Code-DOM tree. This creates proxy code that uses the service.

ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit1);

if (warning == 0) // If zero then we are good to go

{

// Generate the proxy code

CodeDomProvider provider1 = CodeDomProvider.CreateProvider("CSharp");

// Compile the assembly proxy with the appropriate references

string[] assemblyReferences = new string[5] { "System.dll", "System.Web.Services.dll", "System.Web.dll", "System.Xml.dll", "System.Data.dll" };

CompilerParameters parms = new CompilerParameters(assemblyReferences);

CompilerResults results = provider1.CompileAssemblyFromDom(parms, unit1);

// Check For Errors

if (results.Errors.Count > 0)

{

foreach (CompilerError oops in results.Errors)

{

System.Diagnostics.Debug.WriteLine("========Compiler error============");

System.Diagnostics.Debug.WriteLine(oops.ErrorText);

}

throw new System.Exception("Compile Error Occured calling webservice. Check Debug ouput window.");

}

// Finally, Invoke the web service method

object wsvcClass = results.CompiledAssembly.CreateInstance(serviceName);

MethodInfo mi = wsvcClass.GetType().GetMethod(methodName);

return mi.Invoke(wsvcClass, args);

}

else

{

return null;

}

}

}

}