Recently, I was on StackOverflow looking at a question about POSTing a JPG image to a web server. Nearly the exact answer to the question was already available in C#. After translating the answer from C# to PowerShell I realized there should be a tool for that. I have gone down this road before by creating the PowerShellCodeDomProvider. It used an antiquated API to walk C# code and convert it to PowerShell. This time I took advantage of the latest and greatest Roslyn Code Analysis library to walk the syntax tree and produce executable PowerShell.
Converting C# to PowerShell is not very hard. Aside from syntax such as Generics and Lambdas, PowerShell can convert easily to C#. They both run on top of .NET so many of the concepts are the same. The biggest advantage of a tool like this is the time saved by converting 90% of the code to PowerShell. I happen to do it very frequently. It allows PowerShell competent folks to convert examples intended for C# developers into a language they are familiar with. It can also work as learning tool to allow PowerShell developers to understand what C# syntax means.
Roslyn exposes an API for parsing C# code in the Microsoft.CodeAnalysis.CSharp NuGet package. Accessing a syntax tree is as simple as calling the ParseText method.
A very common form of syntax evaluation is conducted using the visitor pattern. PowerShell has a similar API. With C#, you need to extend the CSharpSyntaxVisitor class and override the methods for each type of node. There are nodes for loops, if statements, variables and methods. There are nodes that represent every aspect of the syntax tree. Developing a PowerShell converter required overriding these methods and creating a StringBuilder to put together an executable PowerShell script adapted from the C# code.
After creating the visitor, you can simply pass it into the Accept method of the root node and traverse the tree; generating PowerShell code as you go.
After visiting all the nodes, the visitor has a full StringBuilder and we can return a valid PowerShell script to the user.
There are a few caveats that should be understood.
Since the Rolsyn parser doesn’t have any concept of the scope of variables it is processing, it doesn’t recognize static members. It’s possible to make the engine more intelligent but will need a little work.
It’s just not implemented yet. It could be possible but will require some doing.
The concept of a lambda doesn’t exist in PowerShell. It could be accomplished with pipelining to cmdlets such as Where-Object, Select-Object and ForEach-Object but would also need some doing.
I’d love to hear your feedback below.