Running PowerShell from NAV

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.

The framework

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:

    RunningPowerShellfromNAV01

  • 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:

RunningPowerShellfromNAV02

  • 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:
    RunningPowerShellfromNAV03 

    Compiled it in memory:

    RunningPowerShellfromNAV04 

    And use it with Reflection:

RunningPowerShellfromNAV05

And there is our framework.

Usage

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!):

RunningPowerShellfromNAV06

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:

RunningPowerShellfromNAV07

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:

RunningPowerShellfromNAV08

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!

The Download

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:

RunningPowerShellfromNAV09

In the bottom, you see that it returns a boolean. The example code looks a little bit different then:

RunningPowerShellfromNAV10

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!

Enjoy!

5.00 avg. rating (99% score) - 7 votes

Permanent link to this article: https://www.waldo.be/2014/12/17/running-powershell-from-nav/

18 comments

10 pings

Skip to comment form

    • Remco Reinking on December 17, 2014 at 3:10 pm
    • Reply

    In one word: Wonderful
    In two words: just superb
    In three words : thanks for sharing

      • waldo on December 17, 2014 at 3:22 pm
        Author

      Thanks .. enjoy 😉

    • Marco V on December 18, 2014 at 2:32 pm
    • Reply

    Hi Waldo,

    Great initiative. But I’m probably missing something. When trying to run it (after setting up). I get this error.

    Microsoft Dynamics NAV
    —————————

    Een aanroep voor System.Management.Automation.RemoteRunspace.Open is mislukt met dit bericht: Connecting to remote server failed with the following error message : The client cannot connect to the destination specified in the request. Verify that the service on the destination is running and is accepting requests. Consult the logs and documentation for the WS-Management service running on the destination, most commonly IIS or WinRM. If the destination is the WinRM service, run the following command on the destination to analyze and configure the WinRM service: “winrm quickconfig”. For more information, see the about_Remote_Troubleshooting Help topic.
    —————————
    OK
    —————————

    It’s on NAV2015 on Windows 8.1, all in one box and I’m a local admin. I tried localhost and my own pc name.

    I’m still looking myself but maybe it rings a bell at your side. If I find a cause and solution, I’ll share it to the community.

      • waldo on December 18, 2014 at 2:44 pm
        Author

      Well .. not sure in Windows 8.1 .. but I’m quite sure your PowerShell is not configured well. Did you do a “Enable-Psremoting” in PowerShell? Just a wild guess…

    • Marco V on December 18, 2014 at 2:48 pm
    • Reply

    Hi Waldo, I’m just trying this and it seems to get me a bit further. (There’s probably a PS command too)

    Open the command prompt as administrator and type: “winrm quickconfig”

    Choose “Yes” at the question to configure the change. One remark: you can’t have any active public networks active.

    • Jurica Bogunovic on January 5, 2015 at 7:48 pm
    • Reply

    Hi Waldo,

    This blew my mind at NAV Tech Days, thanks a lot for sharing!

    I did some playing around with this, and found that any Powershell commands that would normally open a window, when run through PS Matrix will result in the process running in the background. Why would that be? Is it a hard limitation of the way the solution is implemented (with begininvoke/endinvoke)?

    For reference, I used following command:
    Start-Process notepad -PassThru

    Note that -PassThru was used only because it provides the return value, and PS Matrix errors out if no return value is used.

    With a code change to FINDFIRST function and to property loop, PS Matrix can be made to not require the return value, yet notepad still ends up running as background process even without -PassThru.

    Thanks,

    Jurica

      • waldo on January 6, 2015 at 8:37 am
        Author

      Thanks for the comment – it was nice meeting you at NAVTechDays.

      If I remember correctly – we had to use the begininvoke/endinvoke (which is an asynchronous (background) process), just because C/AL doesn’t want to take the “Invoke” method, because of the overloading. So yes, no way arround, I’m afraid.

      Keep in mind: you can always create your own wrapper, so that the “Invoke” does work .. but I didn’t want to do that .. . This being said, you could create your wrapper in memory, same way as we did for the object properties :-).

      Just thinkin’ out loud ..

    • Konstantin on March 6, 2015 at 3:10 pm
    • Reply

    Hi Waldo,
    When I try to use Get-NAVServerConfiguration DynamicsNAV71 in your Matrix Page, it’s return only one Property “Count”. Sound like real properties on one level down but I have no Idea how to pull them from there.
    Any help would be appreciate.

    Cheers,
    Konstantin

  1. Hello Waldo,

    I tried it and worked wonderfully. Really a great tool 🙂
    I meant to ask you, can I have your permission to use it on a tool I’m building for assisted merging (to improve it, rather) and publish the tool with that code included in it?
    In case you want to check it first, you can find it here:
    http://msnav.es/merging-information-download/

    Thank you again and good work!

      • waldo on June 8, 2015 at 9:37 am
        Author

      Sure, man, do as you like. A small referral to my blog is always appreciated ;-).

  2. Hi Waldo

    As promised in Reading, I finally got round to investigating the predicate problem and blogged about it below (you probably got a few pingbacks from WP anyway)

    https://geeknikolai.wordpress.com/2015/07/06/using-net-predicate-or-constraints-on-type-in-nav/

      • waldo on July 8, 2015 at 9:40 am
        Author

      Thanks, Nikolai! Great contribution!

  3. hi waldo, do you know, if the powershell consumes a concurrent user? scenario: if all concurrent users are in use (by employees, …), can an administrator connect to nav service and do some tasks at this time or is it needed that at least one connection gets lost ? appreciate your answer. regards jonathan

    • Bert Oosthuizen on February 25, 2019 at 9:35 am
    • Reply

    Hi Waldo,
    Sorry for Digging up graves on this post, but i came across your blog when trying to implement powershell directly in Nav (2015).
    Your example works perfectly for me, but when i try to extend it, I am getting errors:
    – On the Page you call OpenPsRunspace in OnOpenPage.
    – In that function you call LoadModule(‘C:\Program Files\Microsoft Dynamics NAV\90\Service\NavAdminTool.ps1’);
    – All this works perfectly. however, the moment I add an additional Module to load I get an error:
    – LoadModule(‘C:\SomeScript.ps1’);
    – SomeScript.ps1 Contains One line: Import-Module ‘C:\SomeCmdLet.psm1’
    – I get this error:

    Microsoft Dynamics NAV
    —————————

    A call to System.Management.Automation.PowerShell.EndInvoke failed with this message: The term ‘C:\SomeScript.ps1’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
    —————————
    OK
    —————————

    Does this have something todo with the RunSpace? I have no idea why this is failing.
    Your help would realy be appreciated

    /Bert

      • waldo on March 15, 2019 at 4:33 pm
        Author

      Hi,
      I happen to have had the same question twice, so I’m going to have to answer the same:
      to be honest, I don’t do things like this anymore. If you look at my latest session at NAVTechDays, I even advocate to not use DotNet anymore.. and go for a service-based-architecture (like Azure Functions).. . So I’m not going to be able to help you here, I’m afraid…

  4. Hi this is old but still nice.
    Have you been able to run this on a local docker container to connect to your host.

      • waldo on March 15, 2019 at 4:32 pm
        Author

      Hi,
      To be honest, I don’t do things like this anymore. If you look at my latest session at NAVTechDays, I even advocate to not use DotNet anymore.. and go for a service-based-architecture (like Azure Functions).. . So I’m not going to be able to help you here, I’m afraid…

  1. […] Continue reading » […]

  2. […] More information can be found on my blog as well:http://www.waldo.be/2014/12/17/running-powershell-from-nav/ […]

  3. […] and the tenants to a NAV user interface.  I am running Powershell scripts from NAV (thanks Waldo) and things are looking good so […]

  4. […] do this I used and extended the PowerShell functions from Waldo. The extension includes being able to handle XML output from PowerShell, similar to what Waldo uses […]

  5. […] since Waldo released a Powershell Wrapper for NAV (which is what TIM uses) and I was getting this error, I thought it would be interesting to make a […]

  6. […] since Waldo released a Powershell Wrapper for NAV (which is what TIM uses) and I was getting this error, I thought it would be interesting to make a […]

  7. […] compile code using C# compiler. And reading it I had to laugh, because I recognised it as exactly the same solution that Waldo is using in the post I referenced in my first blog. So I have come full circle […]

  8. […] look at Waldo Blog to achieve this functionality http://www.waldo.be/2014/12/17/running-powershell-from-nav/ […]

  9. […] look at Waldo Blog to achieve this functionality http://www.waldo.be/2014/12/17/running-powershell-from-nav/ […]

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.