Silver Light and Blue Sky

C# and Infrastructure. Code is everything.

3 issues for using PSCmdlet binary module

I use PSCmdlet binary module code with C# in order to automate operation on Windows Server. Development with C# and execution speed are the pros for me. However there are issues I can't ignore. I will describe these issue and I wish PSCmdlet binary module solve these issues in the near future.

f:id:tanaka733:20150407010038p:plain

Poor compatibility with async/await and Rx (Reactive Extensions)

If I call async method or Rx Observable method in Cmdlet and call Write-Object after await, errors like below sometime occur.

The WriteObject and WriteError methods cannot be called from outside the overrides of the BeginProcessing, ProcessRecord, and EndProcessing methods, and only from that same thread. Validate that the cmdlet makes these calls correctly, or please contact Microsoft Support Services.

This is due to SynchronizationContext.Current is null in Cmdlet class.

To solve this, one idea is providing custom SynchronizationContext. AwaitablePSCmdlet is a good solution by sunnyone.

A base class that enables to use async/await (cf http://sunnyone41.blogspot.jp/2014/06/pscmdletasyncawait.html)

Another idea for using Rx is implementing producer-consumer pattern with BlockingCollection.

gist.github.com

Difficult to configure Assembly Binding

The assembly binding is sometime required when I use 3rd-party library in Cmdlet class

Configuring Assembly Binding Redirection

In my case, Google APIs Client library is the case. I must configure in app.config as below.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Net.Http.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.2.22.0" newVersion="4.2.22.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

However, it is difficult to configure assembly binding in PSCmdlet binary module. Here is a stackoverflow thread about this.

stackoverflow.com

To solve this issue, we should configure GAC and powershell.exe.config. But it is hard to accept because it influences the entire operating system. I'd like to configure separately for each module or process, but I can't find any solution so far.

Difficult to load configuration file

This is the same issue of previous one as in terms of app.config. If I want to provide configuration to Cmdlet from app.config as well as Console Application, it is difficult to configure. Only global powershell.exe.config is effective for configuration.

stackoverflow.com

To configure appdomain's configuration is one solution. But I worry about by-effect in appdomain. So, in my case Cmdlet receives app.config path and parse xml and pass configurations to logic class as below.

gist.github.com

I understand this solution is only valuable if logic class can receive configuration directly (without ConfigurationManager).

Summary

These 3 issues are critical for me to use PSCmdlet binary module. However PSCmdlet is necessity for automating in Windows Server. I will approach better solution for these.

Released OpenForPSCmdlet VS extension v1.1

OpenForPSCmdlet helps debugging your Cmdlet binary module writing C# or VB.

visualstudiogallery.msdn.microsoft.com

After install this VS extension, you can right click "Open for PSCmdlet" in your Cmdlet class.

f:id:tanaka733:20150203010609p:plain

Then run build and open PowerShell console with Importing your Cmdlet module.

f:id:tanaka733:20150203011143p:plain

In the latest version, VS attaches PowerShell console process and you can debug directly.

f:id:tanaka733:20150320010433p:plain

This extension is opens source. Your comments and requests are welcome.

github.com

Execute MSDeploy from C# program code like an API

I'm now working on constructing build & deploy ASP.NET applications to several IIS Web servers. I use MSBuild and MSDeploy commands. To be specific, making a zip package of ASP.NET application on CI server and deploy it to Web servers. A zip packaged can be deployed with *.cmd file automatically generated by MSBuild command, but I want to use MSDeploy command in C# code because I automate some operations like service in and out from a load balancer with C# code.

Finally I found the way to execute MSDeploy in C# code. However there are few documentation about it... I describe how to write it.

First, install "Web Deploy 3.5" into Web servers and deploying client (and also your development machine). After installed, add "Microsoft.Web.Deployment.dll" reference to your project. It locates at C:\Program Files\IIS\Microsoft Web Deploy V3. A sample code is here.

There are many parameters in MSDeploy configurations. Please see the comment.

Sample execution result is here.

BytesCopied: 6487389
Added: 118
Updated: 4
Deleted: 0
Errors: 0
Warnings: 0
ParametersChanged: 0
TotalChanges: 122

It's much better this way because it's easy to write exception handling than MSDeploy command line.

(This post is an English Translation of my original Japanese post.)

How to show AWS RDS metrics on NewRelic using C#

I'd like to introduce how to show AWS RDS metrics on NewRelic using C#. There is an Amazon RDS Plugin devloped by Ruby, but I have developed by C# because I want to customize components.

Here is a chat of this plugin. This plugin can show a metric (CPU usage in this case) of several instances.

f:id:tanaka733:20130921202837p:plain

Let's move on to the data structure of sending New Relic API.

Read more