Using PowerShell in a .NET installer for a SharePoint App
At Puzzlepart we have created a time tracking application and we have an .exe installer to provision a site, and create all lists and content types needed. Some weeks ago we decided to have the installer deploy the WSP as well, and not only to post-deploy work.
I already had a PowerShell script at hand which deployed the WSP with some extra functionality like uninstalling a previous version and waiting to make sure the deploy timer job finished and that the WSP was properly deployed and installed before ending. Just the nifty script I needed for the job.
I fired up Visual Studio and in no time I had embedded the .ps1 script as a resource and was invoking it runtime from .NET.
var asm = Assembly.GetExecutingAssembly();
Stream stream = asm.GetManifestResourceStream("Pzl.Did.Installer.wspdeploy.ps1");
string script;
using (StreamReader reader = new StreamReader(stream))
{
script = reader.ReadToEnd();
script = script.Replace("$webAppUrl", webAppUrl);
}
RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
runspace.Open();
RunspaceInvoke rsi = new RunspaceInvoke();
ScriptBlock scriptblock = rsi.Invoke("{" + script + "}")[0].BaseObject as ScriptBlock;
var objects = scriptblock.Invoke();
foreach (PSObject psObject in objects)
{
var solution = psObject.BaseObject as SPSolution;
if (solution != null && solution.Deployed)
{
Console.WriteLine("WSP Deployed");
}
Console.WriteLine(psObject);
}
Now, let’s step back for a second. Being a Reflector addict I’m actually very aware that SharePoint PowerShell cmdlet’s are using the regular SharePoint API’s internally. In this case for example the SPSolution class. So why on earth did I hack in invoking a PowerShell script instead of using the native SharePoint API directly?
I had made the existing code more complex by:
- Embedded a resource
- Added a new DSL
- Added code not easily read
Lucky for me my colleague Mads (@madsnissen) do code review and sent me an e-mail with the quote:
What is it that your PowerShell script does which the native API can’t provide?As I know Mads pretty well the understatement hit me right in the gut, and of course I didn’t have a good answer, as there is none. I had as a coder made a stupid mistake (or “bæsjet pÃ¥ leggen” as we say in Norwegian).
Using .NET to create new cmdlet’s is good idea, invoking PowerShell from .NET is usually not. Take the code from the cmdlet and invoke it native instead.