Automatic Monitoring and starting NAV services

I was recently requested to create a script that would monitor NAV services and make sure that they are always up and running, and also e-mail report our support staff if some services were found down and/or cannot be started.

I checked Suresh Kulla's blog about the scheduling NAV Services to restart.
Suresh's approach uses NAV Management dll's command "Get-NAVServerInstance", which is not quite adequate for our needs. We have several different NAV versions running in development environment, and each version has a different management dll version for managing NAV services. Therefore I had to get the NAV Services that are marked as automatic start but are not running the Old School way, and load and use the appropiate Management Service dll on-the-fly.

I found a discussion about looping the services and started building my solution around it.

The powershell command I used is "Get-WmiObject Win32_Service", and I filter services with Name "*MicrosoftDynamicsNAVServer*", whose startmode is Auto, and state is not Running.
I checked also command Get-Service, but the problem with that command is that the returning object properties do not include path for the service executable. This is needed when we want to find out where the correct version of Microsoft.Dynamics.Nav.Management.dll is located.

    $myNavProcesses =  Get-WmiObject Win32_Service -ComputerName . |`
        where  {($_.startmode -like "*Auto*") -and `
                ($_.Name -like "*MicrosoftDynamicsNavServer*") -and `
                ($_.state -notlike "*Running*")

Once all the non-running automatic services are gathered into an object, they can be looped through and check individually the Management dll location, load it dynamically into PowerShell instance, try starting the service with "Set-NavServerInstance -start" command, and finally unload the Management dll. All found malfunctioning services are written into a log file too.

EDIT 2018-09-24: Remove-Module does not fully unload the dll, so we have to start a new PowerShell instance, load the dll there and after each service scrap the instance. Fixed code below and also in the attached txt-file:

    $myNavProcesses | ForEach-Object {
        $tmpService = $_.Name
        $serviceDir = ($_).PathName.split('"')[1].replace("\Microsoft.Dynamics.Nav.Server.exe","")
        $session = New-PSSession -ComputerName .
        invoke-command -Session $session {Import-Module $using:serviceDir\Microsoft.Dynamics.Nav.Management.dll -Force}
        invoke-command -Session $session {Set-NavServerInstance $using:tmpService -start}
        Remove-PSSession $session

After all the services have been run through, I re-check non-running services that are marked for automatic startup type to find out what services failed to restart, store them in another variable and finally e-mail the results to servicedesk.

The solution worked just great when it was run in PowerShell interactive session. Next step was to use Windows Scheduler to schedule it so it will be running every 10 minutes. I found a Spiceworks article how to do it.
There is also TechNet articles around, but they did not have the -ExecutionPolicy setting described. Also remember to check the "Run with highest privileges", or you will get error "Access is denied. You need to be a member of the local Administrators group on the server to run this cmdlet."

After scheduling the script on a development server, I tested it and much to my surprise it did not work. The variable that should contain all failing services was always empty, and the script did not start the services.
I found some posts where other administrators wondered WMI queries that do not return objects when they are run from Scheduled tasks, but there was no solution. After three hours of vigorous testing and small changes I was ready to give up and decide that the scripts just does not work with the available version combination of Windows Server and Powershell. On my own laptop the scheduling worked all the time nicely.

I started closing the editor windows, AND THEN THE DAMN SCRIPT RUN SUCCESSFULLY!
It seems that powershell ISE editor somehow locked the environment and prevented the script from running correctly. After PS ISE was closed, the scheduled task finished flawlessly, email and everything.

Next step is to modify the script so it will work also with Azure SQL and handle the Keyfiles correctly.
I am also planning to write a blog post of its own about how to check Job Queues and make sure Job Queue cards are restarted, so stay tuned!

For your convenience I have added the downloadable script to this blog post. Enjoy!

EDIT: upload of .ps1 file failed, so I attached the file as .txt. The script includes interactive messaging part in the end, it can be safely deleted if you do not need it.
Thank you Esa Elo for support me with PowerShell syntax!

Comment List
  • If you run into a problem where the script seems to be running nicely, but the services do not get started, you have to enable remote execution with command:
    Enable-PSRemoting -Force

    This command enables remote command execution that is needed when you start a new PS session.