Coffee Break: Make your (Windows PowerShell) life easier


Anyone who uses Windows PowerShell regularly will be familiar with re-typing the names of Windows PowerShell cmdlets they already used many times before. In this post we will show a couple of examples of creating functions and store them in your profile to reduce the amount of re-typing needed in order to make your life easier.

Customer Story

Ever find that you reuse the same PowerShell cmdlets again and again? Import-Module, then Get-NAVServerInstance, Get-NAVServerConfiguration, and repeat typing servername like DynamicsNAV90 as parameter. This post shows how you can create functions for this, put them into your profile and then not have to re-type these commands. You can even put the Dynamics NAV Server name into the profile, and get for example DatabaseName in just two steps (only one line of scriping):

  1. Open Windows PowerShell.
  2. Enter Get-NAVConf DatabaseName.

Example – Get NAV Server Configuration Value

The very common Windows PowerShell script to read your Dynamics NAV Server configuration values:

import-module 'C:\Program Files\Microsoft Dynamics NAV\90\Service\Microsoft.Dynamics.Nav.Management.dll'
Get-NAVServerConfiguration DynamicsNAV90

This returns a list of all configuration parameters, not just the one you were looking for. Here is a way to look up a specific parameter, for example DatabaseName:

$Conf = Get-NAVServerConfiguration DynamicsNAV90
($Conf | where { $_.GetAttribute("key") -eq "DatabaseName" }).Value

But this is two lines and a bit more complex than just running Get-NAVSercerConfiguration. To make it easier to run, we can bake it into a function: Just surround the lines with Function Get-NAVConf{ “ and of course an ending }. Adding a parameter and a bit extra, it could look like this:

$NAVServerInstanceName = "DynamicsNAV90"
$VersionNo = 90
Function Get-NAVConf{
Param
(
  $KeyName
)
Import-Module "C:\Program Files\Microsoft Dynamics NAV\$VersionNo\Service\Microsoft.Dynamics.Nav.Management.dll"
Write-Host "$KeyName ="
if (!$KeyName){ Get-NAVServerConfiguration $NAVServerInstanceName}
$Conf = Get-NAVServerConfiguration $NAVServerInstanceName
($Conf | where { $_.GetAttribute("key") -eq $KeyName }).Value
}

After running this once, we have the new function Get-NAVConf available to call like this:

Get-NAVConf DatabaseName

Or call it without a parameter to get a list of configuration values.

Profile it

Run this to see your profile:

Notepad $profile

Whatever script you put into this file will run when you start your Windows PowerShell environment. So copy your function into this file, and you will have it available every time you start PowerShell.

Note:
The Dynamics NAV Management module is version-specific, so you must import the relevant version, such as Dynamics NAV 2016:

Import-Module "C:\Program Files\Microsoft Dynamics NAV\90\Service\Microsoft.Dynamics.Nav.Management.dll"

This sets the scope for the Windows PowerShell session to Dynamics NAV 2016, so if you sometimes use Windows PowerShell for different versions of Dynamics NAV, you might want to consider having a profile for each, so that you can load the management module for the version of Dynamics NAV that you will be working on.

Or enclose script in your profile file with <# … script … #> to comment it, then it won’t actually run but is always ready at hand to copy and paste into Windows PowerShell by just opening your profile file:

Notepad $profile

What else

Just as an example, another useful function to have in your profile file could be to look up the startup parameters for your Dynamics NAV Server service in the application log. Something that is a pretty common task which will otherwise take you into the Event Viewer. Doing it from Windows PowerShell means one less reason to leave your PowerShell environment:

$NAVServerInstanceName = "DynamicsNAV90"
$NAVEventProviderName = "MicrosoftDynamicsNavServer`$$NAVServerInstanceName"

Function Get-NAVStartup
{
Param
(
  $Pattern
)

If (!$pattern){$pattern = "/$NAVServerInstanceName/"}
Write-Host "Pattern = $pattern"
$Events = Get-WinEvent -ProviderName $NAVEventProviderName -MaxEvents 100
$Events | Select-String -inputobject {$_.message} -pattern $Pattern
#https://blogs.msdn.microsoft.com/nav/2015/06/23/coffee-break-monitoring-and-troubleshooting-nav-services/
}

Run it without parameters to get the startup parameters, or set the pattern parameter to look up something specific.

What do you do?

Have any really useful functions? Helpful $profile tips? Feel free to share in comment below.

 

Best regards,

Jasminka Thunes, Escalation Engineer Dynamics NAV EMEA

Lars Lohndorf-Larsen, Escalation Engineer Dynamics NAV EMEA

Bas Graaf, Senior Software Engineer Dynamics NAV

 

Comments (3)

  1. waldo says:

    Great tip 🙂

    Other Scripts to make your life easier:
    http://www.github.com/waldo1000
    🙂

  2. Martin Kuhn says:

    You can enhance the Addon menu in Powershell ISE by dynamically adding all available NAV Versions (requires a corresponding folder structure):

    $psise.CurrentPowerShellTab.AddOnsMenu.Submenus.Clear()

    $loop = 1

    do
    {
    if($loop -eq 1)
    {
    $BasePath = “C:\NAV\NAVServer”
    $ModuleName = “Microsoft.Dynamics.Nav.Management.dll”
    $menutitle = “Load NAV Server CmdLets”
    $type = “Server”
    }

    if($loop -eq 2)
    {
    $BasePath = “C:\NAV\Clients”
    $ModuleName = “Microsoft.Dynamics.Nav.Model.Tools.dll”
    $menutitle = “Load NAV Client CmdLets”
    $type = “Client”
    }

    $full = Get-ChildItem $BasePath -Filter $ModuleName -Recurse

    $MyMenu = $psise.CurrentPowerShellTab.AddOnsMenu.Submenus.Add($menutitle,$null,$null)

    $dict = @{}

    foreach($file in $full)
    {
    $str = $file.Directory.ToString()
    $filename = $file.FullName.ToString()
    $str = $str.Substring($str.IndexOf($BasePath) + $BasePath.Length + 1)
    $fileversion = Get-Item $filename | % VersionInfo | % ProductVersion

    $i = $str.IndexOf($tag)
    #if ($i -ne -1)
    if(!$dict.ContainsKey($fileversion))
    {
    $dict.Add($fileversion,””)
    $code = “function Prompt { “”NAV $type $fileversion $(Get-Location)>”” }”
    $code = $code + ” Import-Module ‘” + $filename.ToString() + “‘ -WarningAction SilentlyContinue | Out-Null”

    $MyMenu.Submenus.Add($fileversion,[Scriptblock]::Create($code),$null) | Out-Null
    }
    }

    $loop ++
    }
    while($loop -le 2)

    $MyMenu = $psise.CurrentPowerShellTab.AddOnsMenu.Submenus.Add(“Tools”,$null,$null)
    $MyMenu.Submenus.Add(“Addon Menü löschen”,{$psise.CurrentPowerShellTab.AddOnsMenu.Submenus.Clear()},$null) | Out-Null

    $code = “function prompt {`”PS `$(`$executionContext.SessionState.Path.CurrentLocation)`$(‘>’ * (`$nestedPromptLevel + 1)) `”}”
    $MyMenu.Submenus.Add(“Prompt zurücksetzen”,[Scriptblock]::Create($code),$null) | Out-Null

    $code = “if (!(test-path `$profile.AllUsersCurrentHost)) {new-item -type file -path `$profile.AllUsersCurrentHost -force} psEdit `$profile.AllUsersCurrentHost”
    $MyMenu.Submenus.Add(“Edit Profile”,[Scriptblock]::Create($code),$null) | Out-Null

  3. Hi Waldo, Martin,

    Thanks for comments! Great idea to add each NAV version / component to the Addon menu!