Lots to blog about .. . After all my sessions in the different conventions, I promised to blog the solutions, the scripts that I used during the sessions. Well, let’s start with the most
interesting one .. at least in my opinion ;-).
Not a script
Indeed .. I’m blogging about PowerShell .. and it isn’t even a script! It is in fact a set of objects to execute PowerShell from within C/SIDE. To be completely honest .. I didn’t create it. It’s actually one of my developers, who’s really good in .NET, that created it, I was merely someone to throw ideas, and to motivate him to go into a direction that he wouldn’t take. I’m that kind of guy .. that lets you do stuff you don’t want to :-).
This time, I didn’t want him to build any dll. It had to work in C/SIDE and in C/SIDE only. That was our mission. The reason for that was that I didn’t want to depend on any deployment-issues, dll-version-issues, or any kind of issues that you might run into when you’re using dll’s.
We baptized it “PSM”, being “PowerShell Manager” (let’s just say that finding names for frameworks is not one of our strong points ;-)). And PSM consists of 3 layers (codeunits):
A PowerShell Wrapper: this codeunit manages your “RunSpace”, like you have when you’re using PowerShell in a conventional manner. It is able to open a runspace with given credentials (for this, we created a simple setup table with a page), it can invoke PowerShell CmdLets or Scripts, add parameters to a command, … . It’s basically a wrapper to easily use “System.Management.Automation.Runspaces.Runspace” and “System.Management.Automation.PowerShell”. Here is a screenshot:
When you execute a CmdLet, you always get something back. And that is an object collection. In NAV terms: a table. But obviously, a collection of objects is much richer than any table .. plus .. we wouldn’t know how that table would look like. So, we decided to create a codeunit PsObject Collection, which holds a .NET collection of objects, and which you can treat like a record, because we applied some kind of design pattern (that is yet to be described), to facilitate this. Here is a screenshot from within the codeunit, where we simply “map” the statements we expect as it would be a record-object:
Just because we don’t know what we will get back .. we couldn’t facilitate this with a table. A table would have fields .. an object of the object collection contains properties. The third layer will get you to these properties in a generic way. So in a way, it had to be able to loosely bind a string to a property. This should have been easy, because a PsObject has got a member “Properties”. But this isn’t accessible in C/SIDE, because it’s a predicate. There is no way to use “PsObject.Properties” .. because to compiler will fail (C/SIDE does not allow to use predicates). This third codeunit is going to deal with the properties. We called it “PsMemberInfo Collection”. You’d say: create a dll that deals with it, and use that in .NET Interop. We didn’t want to use a dll, remember? So refocus. My colleague went on a loop for this one: he writes the c# code in a stringbuilder, compiles it in memory, and accesses it with Reflection. It was kind of a neat theory .. . So we wrote it in C/SIDE:
Compiled it in memory:
And use it with Reflection:
And there is our framework.
And yes, we can use it. And let’s show you a quite advanced example right away, where we want to pipeline CmdLets to each other (yep .. Also that is possible!):
It will give you all the companies, from all the tenants, from all the serverinstances! But not only commands can be executed. In fact, entire scripts can be executed by simply replace the “AddCommand” to “AddScript”, like this example, which has exactly the same outcome then above:
Also notice the “LoadModule” to load the NAV CmdLets.
We even created a Matrix-page, that prints the results in a Matrix page, like you can see here:
I loaded a script to load ports, and the results are in the matrix. This is obviously a gimmick .. Not really useful in production, I guess ;-). But a cool demo afterall .. at least the attendees at NAVTechDays liked it!
Now you’re wondering .. why all this in screenshots, waldo .. I can’t copy, use, .. that. Well, it didn’t make any sense to just copy all the code in a blog. I decided to put the download on MiBuSo, and on a new site that you’re not familiar with, I guess: Objects4NAV. An initiative from Gunnar (also an Dynamics NAV MVP) that I really like and would like to support .. so that’s why I’ve put it up there as well :-). Here you can find the downloads:
Build on top of this
Well, first a big disclaimer: you get the objects for free, without any obligation for me to support any of this. It’s “as is” and blablabla .. you get what I mean 😉
Anyway .. In the download, you’ll see a “PSO” object as well. This is actually just an example on how you can build wrappers on top of this framework. Like the example in the download is a wrapper for one commandlet: Get-NAVServerInstance. When you do it like that, you’re even able to have strongly typed properties, like:
In the bottom, you see that it returns a boolean. The example code looks a little bit different then:
You see that I can now strongly use the properties.. .
It’s just an example on how you can build on top of this .. you can go much much further, obviously .. .
If you have any feedback, just leave a comment!
Thanks once again to Bart Bourgeois, my colleague who helped to make this happen!