User bulk import with powershell

the ps command to add single users in nav is new-navserveruser. detailed info can be found here:
https://docs.microsoft.com/en-us/powershell/module/microsoft.dynamics.nav.management/new-navserveruser?view=dynamicsnav-ps-2018
https://community.dynamics.com/nav/b/magnosblog/archive/2015/08/26/creating-users-with-powershell

i found a great ps script for bulk import:
https://marcellusnav.wordpress.com/2017/07/31/import-nav-users-from-csv-with-powershell/

to work with that, here is a tutorial:

* start the windows powershell ISE in admin mode. this is needed, because only then your are allowed to create new users in nav.

* create a csv text file with comma as separator. semicolon does not work here. save it e.g. as c:\temp\users.csv. check, if the windows users in the list are created on your server (AD).

UserName,FullName,Email
domain\user1,John,john@test.com
domain\user2,Adam,adam@test.com

* create a new text file and copy the script into the text file, save it as c:\temp\Import-NavUsersFromCSV.ps1

* in the ps ISE write “cd \temp” to change to the working directory.

* Import-Module .\Import-NavUsersFromCSV.ps1
to load the new script

* $Permissions = (‘SUPER’)
to set the default user permissionset for the new users

* at last:
Import-NavUsersFromCSV -NavVersion 100 `
-NavServerInstanceName ‘DynamicsNAV100’ `
-AuthenticationMethod Windows `
-ImportFilePath ‘C:\Temp\users.csv’ `
-PermissionSets $Permissions

result:
Creating domain\user1
Verbose: Opening admin connection to ServerInstance ‘MicrosoftDynamicsNavServer$DynamicsNAV100’
Verbose: Admin connection to ServerInstance ‘MicrosoftDynamicsNavServer$DynamicsNAV100’ has been opened
Verbose: Ausführen des Vorgangs “New-NAVServerUser” für das Ziel “ServerInstance = MicrosoftDynamicsNavServer$DynamicsNAV100, Sid = S-1-5-21-236
3956306-4252412874-2321867446-1054, WindowsAccount = domain\user1”.
Verbose: Closing admin connection to ServerInstance ‘MicrosoftDynamicsNavServer$DynamicsNAV100’
Verbose: Admin connection to ServerInstance ‘MicrosoftDynamicsNavServer$DynamicsNAV100’ has been closed
Verbose: Opening admin connection to ServerInstance ‘MicrosoftDynamicsNavServer$DynamicsNAV100’
Verbose: Admin connection to ServerInstance ‘MicrosoftDynamicsNavServer$DynamicsNAV100’ has been opened
Verbose: Ausführen des Vorgangs “New-NAVServerUserPermissionSet” für das Ziel “ServerInstance = MicrosoftDynamicsNavServer$DynamicsNAV100, Permi
ssionSetId = SUPER, Sid = S-1-5-21-2363956306-4252412874-2321867446-1054, WindowsAccount = domain\user1”.
Verbose: Closing admin connection to ServerInstance ‘MicrosoftDynamicsNavServer$DynamicsNAV100’
Verbose: Admin connection to ServerInstance ‘MicrosoftDynamicsNavServer$DynamicsNAV100’ has been closed
Creating domain\user2
Verbose: Opening admin connection to ServerInstance ‘MicrosoftDynamicsNavServer$DynamicsNAV100’
Verbose: Admin connection to ServerInstance ‘MicrosoftDynamicsNavServer$DynamicsNAV100’ has been opened
Verbose: Ausführen des Vorgangs “New-NAVServerUser” für das Ziel “ServerInstance = MicrosoftDynamicsNavServer$DynamicsNAV100, Sid = S-1-5-21-236
3956306-4252412874-2321867446-1055, WindowsAccount = domain\user2”.
Verbose: Closing admin connection to ServerInstance ‘MicrosoftDynamicsNavServer$DynamicsNAV100’
Verbose: Admin connection to ServerInstance ‘MicrosoftDynamicsNavServer$DynamicsNAV100’ has been closed
Verbose: Opening admin connection to ServerInstance ‘MicrosoftDynamicsNavServer$DynamicsNAV100’
Verbose: Admin connection to ServerInstance ‘MicrosoftDynamicsNavServer$DynamicsNAV100’ has been opened
Verbose: Ausführen des Vorgangs “New-NAVServerUserPermissionSet” für das Ziel “ServerInstance = MicrosoftDynamicsNavServer$DynamicsNAV100, Permi
ssionSetId = SUPER, Sid = S-1-5-21-2363956306-4252412874-2321867446-1055, WindowsAccount = domain\user2”.
Verbose: Closing admin connection to ServerInstance ‘MicrosoftDynamicsNavServer$DynamicsNAV100’
Verbose: Admin connection to ServerInstance ‘MicrosoftDynamicsNavServer$DynamicsNAV100’ has been closed

the “change password at next login” flag is not set. this is only set if you use the -ChangePasswordAtNextLogOn option with the New-NAVServerUser command.

 

Advertisements

Performance compare tests between Nav 2013 and Nav 2017

There were some discussions about the newer Nav versions performance. As for my own experience, i can say Nav 2017/2018 releases are quite slow.

To get a better feeling about that i did the following:

I converted Nav 2013 Cronus db (build 46056) to Nav 2017 (build 13682) by simply run the convert job in the dev. env. nothing more. then created a nav service for the converted nav2013-db.

test scenario: i wanted to test the load time for the item list page. in many huge database there can be 1000s and 1000s of items. it’s a very important page, very often loaded per day by many people. so high peformance would be a good thing. in both databases are the same no. of items: 145. in both pages are the same columns/fields in the same order shown. i have the same nav system, same binaries, but different db. so the situation is quite ok for a valid comparison.

next step: i wrote a simple test cu for loading the item-list page.

[Test] TestItemList()
// ItemList / TestPage / item list
// dt / DateTime
dt := CURRENTDATETIME;
ItemList.OPENEDIT;
MESSAGE(FORMAT(CURRENTDATETIME – dt));

i started the test cu with the simple test function and measured the time:
1. run: 270ms
2. run: 230ms
3. run: 170ms

now copied that test cu to the nav2017 db, ran the same test, measured the time:
1. run: 380ms
2. run: 320ms
3. run: 300ms

WOW!!!!!! simple test, the numbers tell the story!
What’s about other main list pages (customers, vendors, ledger entries and so on)? What about performance of posting processes? What would i measure, if i continue that kind of tests? i think better not measure …

Is that really a progress??? What is the advantage of new features, if the performance lowers and lowers from release to release ???

i think here is a todo for the nav microsoft team.

cheers

 

 

MVP Award part 2 … more or less

mvp-logo

Got mail … not from Microsoft, but from FedEx …

Bildschirmfoto_2017-07-06_04-16-53

So, what does that mean ? Do i get my 2. MVP Award ? A bit Yes and a little bit more of a No. After clarification with Cristina Herero (MVP Program Manager Europe) will MVP Awards given on Oct/16 or later – normally valid for one year, then the candidate will be reevaluated – be extended til July/2018. Veeeery strange, does not feel like a real MVP Award and it’s a bit unfair. But we have to accept that.

All of that because of the changes in the MVP Award Renew Cycle some of us new MVPs get that info in that way.

Like last time: Many, many thanks to my girlfriend for supporting me for so many years in so many ways, bringing light, love and friendliness into my life.

Many thanks to the readers of my Nav blog and the members of the Nav community.

cheers

How to: Create an automation for usage in Navision

The development of a COM component with .Net for usage in Navision needs a special approach. Start with a new C# project, project type Class Library. Set the project to “Make assembly com-visible”. The simple automation provides a string property and a method to show a .net message box.

// a sample code
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace SampleAutom
{
 // the interface, so that the methods and properties are shown in Nav
 // needed attributes InterfaceType and Guid
 [InterfaceType(ComInterfaceType.InterfaceIsDual)]
 // create a new Guid
 [Guid("9304DD04-5EF0-498E-893E-CB644CD34656")] 
 interface IMyInterface
 {
  // set a DispId for each method/property
  [DispId(1)]
  int MsgBox(string message);

  [DispId(2)]
  string Title { get; set; }
 }

 // class attributes
 [ClassInterface(ClassInterfaceType.AutoDual)]
 [Guid("D9E556F3-4D85-45C9-965A-DB3D918528CD")]
 // implement the interface
 public class TestCom : IMyInterface
 {
  string _title = "Dynamics Nav";

  public TestCom()
  { }

  // with property Title you can set/read the title of the msgbox
  public string Title
  {
    get
    { return _title; }
  
    set
    { _title = value; }
  }
  
  // method msgbox returns an integer value according the clicked button
  // Yes = 6, No = 7, Cancel = 2
  public int MsgBox(string message)
  {
    var result = MessageBox.Show(message, Title, 
       MessageBoxButtons.YesNoCancel, MessageBoxIcon.Information);
    return (int)result;
  }
 }
}

To install the new automation run visual studio in admin mode. after restart and loading the project build/compile the project.

Now start Navision and create a new codeunit. In the OnRun trigger add following code:

// TestCom, Automation, 'SampleAutom'.TestCom 
// RetVal, Integer 
CREATE(TestCom);
TestCom.Title := '.Net Msgbox run in Navision';
RetVal := TestCom.MsgBox('Your message text ...');
MESSAGE(FORMAT(RetVal));
CLEAR(TestCom);

Now run the codeunit. It results in:

autom1    autom2

cheers

Import with Rapid Start Services

The Rapid Start Services are an often used tool in Dynamics Nav to export and import data. In that posting i show how the Import works using new feature Item Attributes.

In that sample i want to import a new Item Attribute Value and a new Item Attribute Value Mapping. Item Attribute Values are the concrete values, which an Item Attribute can have, e.g. Item Attribute “Color” can have values red, green, blue. These values can now be added as attributes to a concrete item using table item attribute value mapping.

We start with a new Config. Package. So goto /Departments/Administration/Application Setup/RapidStart Services/Configuration Packages or simply write “Configuration Packages” into the search box. There create a new Config. Package and set ITEMATT as code value and “Item Attributes” as package name. Now we add some lines to the Tables list: 7501 and 7505.

cfg4

Now select Filters in subpage menu Table.
Add a filter for the first line (table 7501). Here we want to filter for Item Attribute with ID 1 (Color): FieldID = 1,Field Filter = 1.
For the 2. line (table 7505) set following filter:

cfg5

Now export the filtered table data to excel using action “Export to Excel” from the main menu Actions. Open the created excel document. So we get the needed format to import some data. Now we change the data. Remove all data lines from table 1 in the excel document except line 1. Now change the values for ID and Value as follows:

cfg2

In the 2. table change the value for “Item Attribute Value ID”:

cfg3

Save the changed document to your documents folder, close Excel. Now we can import the new data. For that click on “Import from Excel”, No. of Package records changes to 1. If you click on the no., you can check import errors in the winow Config. Package records. The imported data is now temporarily saved. To save the data to the target tables, click on “Apply Package” action.

cfg1

Now let’s check, if the data was imported.

cfg6

Goto items list and click on action Attributes in menu Action. All right, the data is correct. You see in the second line Attribute Farbe (= Color) and the new value Brown, right the attribute value list with the new value.

cheers

Check windows client’s execution mode at runtime

If you want to check if the windows client is run in config mode at runtime, then there is an easy method to do that:

// variables
Env : DotNet : System.Environment.'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
cmdArgs : DotNet : System.Array.'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'

// code
cmdArgs := Env.GetCommandLineArgs;
IF LOWERCASE(FORMAT(cmdArgs.GetValue(1))) = '-configure' THEN
  // do something

Method GetCommandLineArgs gives back a string array. In the sample it’s expected, that the -configure parameter is the first parameter. To check all parameters you can do with that code:

FOR i := 0 TO cmdArgs.Length - 1 DO
  IF LOWERCASE(FORMAT(cmdArgs.GetValue(i))) = '-configure' THEN
    MESSAGE('Config mode');

There is an alternative method, also working, but much longer and with low performance. 😉

// variables
cmdLine : Text;
 
// code
cmdLine := LOWERCASE(GetCmdLine);
IF (STRPOS(cmdLine, '-configure') <> 0) OR (STRPOS(cmdLine, '/configure') <> 0) THEN
  Message('Config mode');

PROCEDURE GetCmdLine : Text;
// variables
FileMgt : Codeunit 419
CurrProc : DotNet "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Diagnostics.Process"
MgmtObjSearcher : DotNet "'System.Management, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.System.Management.ManagementObjectSearcher"
MgmtObjColl : DotNet "'System.Management, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.System.Management.ManagementObjectCollection"
MgmtObj : DotNet "'System.Management, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.System.Management.ManagementObject"
Enum : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Collections.IDictionaryEnumerator"
cmdLine : Text;

// code
CurrProc := CurrProc.GetCurrentProcess;
MgmtObjSearcher := MgmtObjSearcher.ManagementObjectSearcher(
  STRSUBSTNO('SELECT CommandLine FROM Win32_Process WHERE ProcessId = %1', CurrProc.Id));

MgmtObjColl := MgmtObjSearcher.Get;
Enum := MgmtObjColl.GetEnumerator;

WHILE Enum.MoveNext DO BEGIN
  MgmtObj := Enum.Current;
  cmdLine += STRSUBSTNO(' %1', MgmtObj.Item('CommandLine'));
END;

EXIT(cmdLine);

cheers