• Michael Intravartolo

Using NetTcpPortSharing for NAV Servers

Recently I came back from three weeks vacation. During my vacation I had made a decision to implement Tcp Port Sharing for the Instance Administration tool used in Advania Azure.

Early last year I published a function that uses the sc.exe to modify a NAV Service startup type. When a NAV Service is installed and configured in setup, the startup type is Automatic (Delayed Start). However, create a new service with Powershell New-NavServerIntance and the startup type is Automatic without the (Delayed Start).

To enable Tcp Port Sharing that same sc.exe function is needed. Interestingly, after I had finished the task and was reading NAV blogs I saw that Waldo just published a powershell function on his blog to do just this.

The script lines I used and added to my Instance Administration powershell scripts are based on my fist sc.exe function but not using the function itself. Now when a new NAV service is created by the tool the startup type is modified and if so selected by the deployment settings, the Tcp Port Sharing is also activated.

By default, the Tcp Port Sharing service is disabled.

The startup type should be changed to Manual. This can be done manually or by an administative powershell script.

1 #Set Startup Mode for NetTcpPortSharing to Manual

2 $command = 'sc.exe \\$Computer config "NetTcpPortSharing" start= demand'

3 $Output = Invoke-Expression -Command $Command -ErrorAction Stop

4 if($LASTEXITCODE -ne 0){

5 Write-Error "$Computer : Failed to set NetTcpPortSharing to manual start. More details: $Output"

6 }

Similar script is used to update the existing NAV Services to both delayed start and Tcp Port Sharing dependency.

1 #Stop NAV Server Instances

2 Get-NAVServerInstance | Set-NAVServerInstance -Stop

3 #Update Startup Type and Dependency on NAV Server Instances

4 Get-NAVServerInstance | foreach {

5 $Service = $_.ServerInstance

6 Write-Host "Working on service $Service"

7 $Computer = 'LOCALHOST'

8 $command = 'sc.exe \\$Computer config "$Service" start= delayed-auto'

9 $Output = Invoke-Expression -Command $Command -ErrorAction Stop

10 if($LASTEXITCODE -ne 0){

11 Write-Error "$Computer : Failed to set $Service to delayed start. More details: $Output"

12 }

13 $command = 'sc.exe \\$Computer config "$Service" depend= NetTcpPortSharing/HTTP'

14 $Output = Invoke-Expression -Command $Command -ErrorAction Stop

15 if($LASTEXITCODE -ne 0){

16 Write-Error "$Computer : Failed to set $Service TcpPortSharing. More details: $Output" -foregroundcolor 17 red

18 }

19 }

20 #Start NAV Server Instances

21 Get-NAVServerInstance | Set-NAVServerInstance -Start

After enabling the Tcp Port Sharing and updating the services they would not start. Event Viewer revealed the reason.

Server instance: CRONUS

The service MicrosoftDynamicsNavServer$CRONUS failed to start. This could be caused by a configuration error. Detailed error

information:System.ServiceModel.CommunicationException: The service endpoint failed to listen on the URI ‘net.tcp://mynavserver.dynamics.is:7046/CRONUS/Service’ because access was denied. Verify that the current user is granted access in the appropriate allowAccounts section of SMSvcHost.exe.config. —> System.ComponentModel.Win32Exception: Access is denied

So I started to ask Bing what I could o. Microsoft MSDN states:

When a net.tcp binding enables port sharing (by setting portSharingEnabled =true on the transport binding element), it implicitly allows an external process (namely the SMSvcHost.exe, which hosts the Net.TCP Port Sharing Service) to manage the TCP socket on its behalf.

Hence, I need to add the Sid of my NAV Service Account to the SMSvcHost.exe.config file. I could do this manually, but I am a programmer!

Another powershell script was born. This one could also be converted to a function. Before executing the script make sure to update the user and domain in the top of the script. Be smart and execute this function before updating the NAV Services with the script above.

#Modify User and Domain to fit your environment

$UserToAdd = 'srvNAV'

$UserDomainToAdd = 'DYNAMICS'

#Initial Values

$UserSidFound = 'false'

$ConfigurationSet = 'false'

#Net.Tcp Port Sharing Service Name

$ServiceName = 'NetTcpPortSharing'

#Get SID for the Service User

$UserSid = ([wmi] "win32_userAccount.Domain='$UserDomainToAdd',Name='$UserToAdd'").SID

#Get Path for SMSvcHost.exe.config file

$SMSvcHostPath = (Get-WmiObject win32_service | ?{$_.Name -like $ServiceName} ).PathName

$SMSvcHostPathConfig = $SMSvcHostPath + '.config'

Write-Host "Reading XML from $SMSvcHostPathConfig"

#Read Config file

$xmlDoc = 1 (Get-Content $SMSvcHostPathConfig)

Write-Host "Looking for access permission for $UserSid"

#Loop through allowed accounts and search for the service user Sid

$allowAccounts = Select-Xml "configuration/system.serviceModel.activation/net.tcp/allowAccounts/add" $xmlDoc

$allowAccounts | ForEach-Object {

$ConfiguredSid = $_.Node.Attributes.Item(0).Value

if ($ConfiguredSid -eq $UserSid) {$UserSidFound = 'true'}

$ConfigurationSet = 'true'

Write-Host "Found SID $ConfiguredSid"


#Act if Access Configuration is not enabled

if ($ConfigurationSet -eq 'false') {Write-Host "Access permission not configured"

$config = 1 '


<add securityIdentifier="S-1-5-19"/>

<add securityIdentifier="S-1-5-20"/>

<add securityIdentifier="S-1-5-32-544" />




<add securityIdentifier="S-1-5-19"/>

<add securityIdentifier="S-1-5-20"/>

<add securityIdentifier="S-1-5-32-544" />



$configurationNode = $xmlDoc.DocumentElement

$newConfig = $xmlDoc.ImportNode($config.DocumentElement, $true)


$allowAccounts = Select-Xml "configuration/system.serviceModel.activation/net.tcp/allowAccounts/add" $xmlDoc

$allowAccounts | ForEach-Object {

$ConfiguredSid = $_.Node.Attributes.Item(0).Value

Write-Host "Found SID $ConfiguredSid"

if ($ConfiguredSid -eq $UserSid) {$UserSidFound = 'true'}

$ConfigurationSet = 'true'



#Add Service User Sid if needed

if ($UserSidFound -ne 'true') {

$nettcp = $xmlDoc.SelectSingleNode("configuration/system.serviceModel.activation/net.tcp/allowAccounts")

$addNode = $xmlDoc.CreateElement('add')

$secIden = $xmlDoc.CreateAttribute('securityIdentifier')

$secIden.Value = $UserSid




Write-Host "Configuration Updated"

#Restart Service if running

if ((Get-Service NetTcpPortSharing).Status -eq "Running") {Restart-Service NetTcpPortSharing -Force}


This script will search for the SMSvcHost.exe.config file, load it and check to see if the NAV Service User is already allowed access. If not then the config file is updated and saved. This script must be executived with administrative privelages.

Perhaps this should be what I started with, but the question; why do we need this, should be answered.

First, modifying the startup mode to delayed start is done to make sure that all the required networking and database processes have been started before the NAV Service starts. This is very important if the SQL Server is running on the same server. On a dedicated NAV Service this is not as important but still recommended.

Secondly, accessing a NAV Service in most cases requires changes to a firewall. Either to open a specific port or setting up a NAT from a public interface. To minimize the number of ports used also minimizes the networking setup and maintenance. If different network permissions or network access is required I recommend using seperate ports for the NAV Services.


Contact Us

Solution Systems, Inc.

3201 Tollview Dr. 

Rolling Meadows, IL 60008

Office: 847-590-3000

Email: info@solsyst.com

Support: 224-345-2020

Support Email: support@solsyst.com

Connect With Us
  • Manufacturing Software | Illinois
  • Manufacturing Software | Illinois
  • Manufacturing Software | Illinois
  • Manufacturing Software | Illinois
  • Manufacturing Software | Chicago
  • Manufacturing Software | Illinois
  • Microsoft Business Podcast
  • Manufacturing Software | Chicago
  • Manufacturing Software | Chicago
  • Manufacturing Software | Chicago
Join our Mailing List

© 2020 Solution Systems, Inc.