This PowerShell script is designed to help troubleshooting Dynamics NAV 3-tier installations by extracting the information that is typically used, rather than looking around in Active Directory to find it manually.
Installing NAV in a 3-tier configuration requires updates to Active Directory. If client connections fail, then often the cause is some missing or wrong Active Directory settings. This script is designed to extract the most likely areas where the problem is.
This script must be run on the machine where NAV Server is installed. It will automatically detect any Windows Services which contain "Dynamics.Nav" in their BinPath, assuming these to be NAV Server instances, and collects Active Directory information for those.
Step1. Open an elevated PowerShell Command prompt on the machine where NAV Server is running. Run the PowerShell command "set-executionpolicy unrestricted" to allow running scripts, then run the following script:
#set-executionpolicy unrestricted
#create folder for each NAV service
$services = get-wmiobject -query 'select * from win32_service where pathname like "%Dynamics.Nav%"'
[string]$Folder = get-location
$Folder = $Folder + "\Results"
foreach ($S in $Services) {
$Path = ""
[string]$SName = $S.Name
new-item -path $Folder -Name $S.Name -type "directory" -erroraction silentlycontinue
$Len=$S.pathname.length
do
{
$Char=$S.Pathname[$Len - 1]
$Len--
} until ($Char -eq '\')
for ($Counter = 0;$Counter -ile $Len;$Counter++) {
$Path = $Path + $S.PathName[$Counter]
}
$Path = $Path.replace('"','')
get-childitem $Path | format-list | out-file "$Folder\$SName\FileList.txt"
$Path = $Path + 'CustomSettings.config'
copy-item "$Path" -destination "$Folder\$SName" -erroraction silentlycontinue
}
$services | format-list name, startname, pathname, status, displayname, Description, status, servicetype, started, state, startmode, systemname, __server | out-file "$Folder\Servers.txt"
# List of NAV Service accounts and SPNs
$UsrArray = @()
foreach ($S in $Services)
{
$Pos = 0
$Usr = ""
[String]$Acct = $S.StartName
$Len = $Acct.length
do {
$Char = $Acct[$Len - 1]
$Len--
if ($Char -eq '\'){$Pos = $Len + 1}
} until ($Len -eq 1)
for ($Counter = $Pos;$Counter -ile $Acct.length;$Counter++) {
[string]$Usr = $Usr + $Acct[$Counter]
}
$Usr
$UsrArray = $UsrArray + $Usr
}
$UsrArray2 = @()
for ($i = 0;$i -lt $UsrArray.count;$i++) {
$Dup = 0
for($j = 0;$j -lt $i;$j++) {
if ($UsrArray[$i] -eq $UsrArray2[$j]){
$Dup = 1
}
}
if ($Dup -eq 0){
$UsrArray2 = $UsrArray2 + $UsrArray[$i]
}
}
$Search = new-object DirectoryServices.DirectorySearcher([ADSI]"")
foreach ($Usr in $UsrArray2){
$Search.Filter = "(SAMAccountName=$Usr)"
$Results = $Search.Findall()
foreach($Result in $Results){
$Usr2 = ""
$Usr2 = $Result.GetDirectoryEntry()
$FileName = $Folder + "\" +$Usr2.SamAccountName + ".txt"
$Usr2 | format-list name, UserAccountControl,SAMAccountName, msDS-AllowedToDelegateTo, objectCategory | out-file $FileName ;$FileName = $FileName + "SPN.txt"
setspn -l $Usr | out-file $FileName
}
}
#setspn x
$FileName = $Folder + "\SetSPNX.txt"
setspn -x | out-file $FileName
# GEt ALL SPNs
$searcher = new-object DirectoryServices.DirectorySearcher([ADSI]"")
$searcher.filter = "(serviceprincipalname=*)"
$Searcher.PageSize = 100
$Searcher.findall()
#set-executionpolicy unrestricted #create folder for each NAV service $services = get-wmiobject -query 'select * from win32_service where pathname like "%Dynamics.Nav%"' [string]$Folder = get-location $Folder = $Folder + "\Results" foreach ($S in $Services) { $Path = "" [string]$SName = $S.Name new-item -path $Folder -Name $S.Name -type "directory" -erroraction silentlycontinue $Len=$S.pathname.length do { $Char=$S.Pathname[$Len - 1] $Len-- } until ($Char -eq '\') for ($Counter = 0;$Counter -ile $Len;$Counter++) { $Path = $Path + $S.PathName[$Counter] } $Path = $Path.replace('"','') get-childitem $Path | format-list | out-file "$Folder\$SName\FileList.txt" $Path = $Path + 'CustomSettings.config' copy-item "$Path" -destination "$Folder\$SName" -erroraction silentlycontinue } $services | format-list name, startname, pathname, status, displayname, Description, status, servicetype, started, state, startmode, systemname, __server | out-file "$Folder\Servers.txt" # List of NAV Service accounts and SPNs $UsrArray = @() foreach ($S in $Services) { $Pos = 0 $Usr = "" [String]$Acct = $S.StartName $Len = $Acct.length do { $Char = $Acct[$Len - 1] $Len-- if ($Char -eq '\'){$Pos = $Len + 1} } until ($Len -eq 1) for ($Counter = $Pos;$Counter -ile $Acct.length;$Counter++) { [string]$Usr = $Usr + $Acct[$Counter] } $Usr $UsrArray = $UsrArray + $Usr } $UsrArray2 = @() for ($i = 0;$i -lt $UsrArray.count;$i++) { $Dup = 0 for($j = 0;$j -lt $i;$j++) { if ($UsrArray[$i] -eq $UsrArray2[$j]){ $Dup = 1 } } if ($Dup -eq 0){ $UsrArray2 = $UsrArray2 + $UsrArray[$i] } } $Search = new-object DirectoryServices.DirectorySearcher([ADSI]"") foreach ($Usr in $UsrArray2){ $Search.Filter = "(SAMAccountName=$Usr)" $Results = $Search.Findall() foreach($Result in $Results){ $Usr2 = "" $Usr2 = $Result.GetDirectoryEntry() $FileName = $Folder + "\" +$Usr2.SamAccountName + ".txt" $Usr2 | format-list name, UserAccountControl,SAMAccountName, msDS-AllowedToDelegateTo, objectCategory | out-file $FileName ;$FileName = $FileName + "SPN.txt" setspn -l $Usr | out-file $FileName } } #setspn x $FileName = $Folder + "\SetSPNX.txt" setspn -x | out-file $FileName # GEt ALL SPNs $searcher = new-object DirectoryServices.DirectorySearcher([ADSI]"") $searcher.filter = "(serviceprincipalname=*)" $Searcher.PageSize = 100 $Searcher.findall()
The script will create a sub folder called Results, which will contain the following information:
Note:
The script uses the command Findall() in two places. This command scans the whole Active Directory. On a very large Active Directory with multiple domains this can take a long time (many minutes) to run.
Decoding the UserAccountControl property
Additional NAV samples
How to boost performance on Dynamics NAV RTC reports
Use PowerShell & other techs to manage NAV Services
Call Dynamics NAV Web Services