Connecting to NAV Web Services from VBScript

The Connecting to NAV Web Services series is coming to an end. I think I have covered the majority of platforms from which you would like to connect and use NAV Web Services – some things are easy and some things are a little harder. I did not cover Flash nor did i cover things like the iPhone or iPod Touch, primarily because I don’t think the demand is there. If I have forgotten any platform/language please let me know and if the demand is there I might make something work.

Why VBScript?

Including VBScript makes it possible to do Web Services from scripting like login, shutdown and maintenance scripts. I know that VBScript can also be used from certain browsers but the real idea behind including VBScript here is to enable command line scripts.

Please read this post to get a brief explanation of the scenario I will implement in VBScript.

Please read this post about how to connect to NAV Web Services from Javascript to get an overall explanation about XML Web Services and how to do things without having proxy classes generated etc.

The primary difference between Javascript and VBcript is actually syntax – most of the things are done in a similar way.

The Script file

I created a file called TestWS.vbs and the code to implement the scenario looks like:

function InvokeNavWS(URL, method, nameSpace, returnTag, parameters) 
    Set xmlhttp = CreateObject("MSXML2.XMLHTTP")
    request = "<Soap:Envelope xmlns:Soap="""+SoapEnvelopeNS+"""><Soap:Body><"+method+" xmlns="""+nameSpace+""">"+parameters+"</"+method+"></Soap:Body></Soap:Envelope>"

    ' Use Post and non-async "POST", URL, false 
    xmlhttp.setRequestHeader "Content-type", "text/xml; charset=utf-8" 
    xmlhttp.setRequestHeader "Content-length", len(request) 
    xmlhttp.setRequestHeader "SOAPAction", method

    ' send request synchronously 
    xmlhttp.send request

    ' 200 == OK 
    if xmlhttp.status = 200 then 
        Set xmldoc = xmlhttp.responseXML 
        xmldoc.setProperty "SelectionLanguage", "XPath" 
        xmldoc.setProperty "SelectionNamespaces", "xmlns:tns="""+nameSpace+"""" 
        Set InvokeNavWS = xmldoc.selectNodes("//tns:"+returnTag) 
        Set InvokeNavWS = nothing 
    end if

end function

' Get the Company list 
function SystemService_Companies() 
    Set SystemService_Companies = InvokeNavWS(systemServiceURL, "Companies", systemServiceNS, "return_value", "") 
end function

' Read one customer 
function CustomerPage_Read(no) 
    Set CustomerPage_Read = InvokeNavWS(CustomerPageURL, "Read", CustomerPageNS, "Customer", "<No>"+no+"</No>") 
end function

' Read Customers 
function CustomerPage_ReadMultiple(filters) 
    Set CustomerPage_ReadMultiple = InvokeNavWS(CustomerPageURL, "ReadMultiple", CustomerPageNS, "Customer", filters) 
end function

sub display(str) 
    WScript.echo str 
end sub

baseURL = "http://localhost:7047/DynamicsNAV/WS/" 
systemServiceURL = baseURL + "SystemService"

soapEnvelopeNS = "" 
systemServiceNS = "urn:microsoft-dynamics-schemas/nav/system/" 
customerPageNS = "urn:microsoft-dynamics-schemas/page/customer"

Set Companies = SystemService_Companies() 
display "Companies:" 
for i = 0 to Companies.length-1 
    display Companies(i).text 
cur = Companies(0).text

customerPageURL = baseURL+escape(cur)+"/Page/Customer" 
display "" 
display "URL of Customer Page:" 
display customerPageURL

Set Customer10000 = CustomerPage_Read("10000") 
display "" 
display "Name of Customer 10000: "+Customer10000(0).childNodes(2).firstChild.nodeValue

Set Customers = CustomerPage_ReadMultiple("<filter><Field>Country_Region_Code</Field><Criteria>GB</Criteria></filter><filter><Field>Location_Code</Field><Criteria>RED|BLUE</Criteria></filter>") 
display "" 
display "Customers in GB served by RED or BLUE warehouse:" 
for i = 0 to Customers.length-1 
    display Customers(i).childNodes(2).firstChild.nodeValue 

display "" 
display "THE END"


The similarity to the Javascript sample is huge (since I am using the same object model), the biggest differences are:

  • The way to encode a URL component in VBScript is by calling escape() – note that escape also exists in Javascript and .net – but there it works differently.
  • Displaying things are done using WScript.echo – this will result in a messagebox if you are using WScript to run the script and a commandline output if you are using CScript (I use CScript)

Running the script

Using the command:

C:\users\freddyk>SCript /nologo testws.vbs

I get the following:


and of course you can now do things as redirecting the output to a file and typing or searching in that file:

image_4 (1)

This is something network administrators are experts in doing – I won’t try to compete in any way.

I hope this is helpful.

Good luck

Freddy Kristiansen
PM Architect
Microsoft Dynamics NAV

Running Code on the Client without deploying COM objects

Yes, it can be done!

No, it isn’t .net code – nor AL code.


It started out as me being a little too fast when stating that you could easily download a file to the Client and attach it to Outlook without any user interaction – and as you might know that is true, but you might also know that if you go the recommended route:

FILE.DOWNLOAD(FileName, ”, ‘<TEMP>’,”, ToFile);

Then you will get an e-mail that looks like this:


People might not assume that this actually is Invoice no. 10103 in PDF format. What you of course want to have is:


So, how do we get there.

I actually did respond to a post on mibuso a while back ( about how this could be done, but that would involve a COM object deployed to all clients and not everybody wants that (although I have posted a method on how to do this automatically).

The problem here is, that always places the file in a temporary directory with a temporary filename – and there is (to my knowledge) no other way to copy a file to the Client.

Assuming that this is correct, how do we then rename a file on the client without having to deploy COM objects?

I said without deploying COM objects, not without USING COM objects

As you know, we can run COM objects on the server or on the Client and one of the COM objects, which ships with Windows can come in handy here. The Windows Script Host – if we instantiate this COM object we can actually give the component a VB Script to execute in the context of the COM component (which would be either on the Server or on the Client).

Windows Script Host

Yes, WSH is legacy – but it is widely used and it is included on all Windows versions from Windows XP and up. I am not going to make this a tutorial on VBScript and WSH – for that you can find a number of good posts on the internet – or start by reading msdn

Creating a script function / method

The method AddCode on the Windows Script Host COM object is used to add sourcecode to the component.

Note, that you need to add an entire function / method in one call and note, that each line needs to be terminated by a CR.

You also need to specify what language you use, the control supports JScript and VBScript.

A VBScript function which returns Hello <name> could look like this:

function Hello(who)
Hello = “Hello “&who
end function

Creating this function in a Client side COM component could look like:

CR := ‘ ‘; CR[1] := 13;
objScript.Language := ‘VBScript’;
‘function Hello(who)’+CR+
‘  Hello = “Hello “&who’+CR+
‘end function’);

The way I write this is, that I try to maintain the structure of the VBScript even though it is inside a string in NAV, maybe I am fooling myself, but I think it is more readable.

Invoking a script function / method

There are two ways of invoking a script method:

Eval – used to invoke a function, and get a return value back.

The above function could be called using


Note – when calling functions, VBScript wants your parameters embraced by parentheses.

ExecuteStatement – used to invoke a method which doesn’t return anything

Let’s rewrite the above function to a method and have the method show a MessageBox:

The VBScript could look like:

sub Hello(who)
MsgBox “Hello “&who, 0, “Title”
end sub

and creating this function in a COM object and calling the method could look like:

CR := ‘ ‘; CR[1] := 13;
objScript.Language := ‘VBScript’;
‘sub Hello(who)’+CR+
‘  MsgBox “Hello “&who, 0, “Test”‘+CR+
‘end sub’);
objScript.ExecuteStatement(‘Hello “Freddy”‘);

Note – when calling methods (or sub’s) VBScript does NOT want the parameters embraced by parentheses.

Some sample scripts

Rename a temporary file

function RenameTempFile(fromFile, toFile)
set fso = createobject(“Scripting.FileSystemObject”)
set x = createobject(“Scriptlet.TypeLib”)
path = fso.getparentfoldername(fromFile)
toPath = path+””+left(x.GUID,38)
fso.CreateFolder toPath
fso.MoveFile fromFile, toPath+””+toFile
RenameTempFile = toPath
end function

As you can see, I am doing exactly what I responded on the mibuso thread here – just in VBScript instead – which then requires no client side install.

BTW this function is actually used in ClausL’s post about sending e-mail with PDF attachments, which proves that we do talk with our colleagues at Microsoft:-). Note that there is no good way of creating a GUID from VBScript – I (mis)use the fact that every instance of Scriptlet.TypeLib gets assigned a new GUID.

Get Machine name

function GetComputerName()
set net = createobject(“”)
GetComputerName = net.ComputerName
end function

I know, that you also can read an environment variable – but this way you can actually get all kind of information on the network though this.

Launch an application

sub Notepad()
set shell = createobject(“WScript.Shell”)
shell.Run “notepad.exe”
end sub

Yes, you can do this by using the Shell object directly in NAV, like:

Shell       Automation       ‘Microsoft Shell Controls And Automation’.Shell


I just wanted to show that you that stuff like this can be done in VBScript too, and note, that the Shell object in VBScript and in NAV is not the same.

Asking a simple question

function Input(question, title, default_answer)
Input = InputBox(question, title, default_answer)
end function

A couple of partners have told me, that they are unhappy with the discontinuation of INPUT from NAV and having to create pages for even the simplest questions. Running the following code:

CR := ‘ ‘; CR[1] := 13;
objScript.Language := ‘VBScript’;

‘function Input(question, title, default_answer)’+CR+
‘  Input = InputBox(question, title, default_answer)’+CR+
‘end function’);

  s := objScript.Eval(‘Input(“How old are you?”, “A simple question”, “”)’);

Brings up this dialog on my machine:


Who knows, maybe somebody can use this as an alternative to INPUT.

Read the RoleTailored Client configuration file

function ReadConfigFile()
set shell = CreateObject(“WScript.Shell”)
folder = shell.ExpandEnvironmentStrings(“%LOCALAPPDATA%”)
if folder = “” then folder = shell.ExpandEnvironmentStrings(“%USERPROFILE%”)&”Local SettingsApplication Data”
  filename = folder&”MicrosoftMicrosoft Dynamics NAVClientUserSettings.config”
set fso = createobject(“Scripting.FileSystemObject”)
set file = fso.OpenTextFile(filename, 1)
ReadConfigFile = file.ReadAll()
end function

Note that I have NOT tested this function under Windows XP – I know that LOCALAPPDATA is not defined on Windows XP and I think the line:

  if folder = “” then folder = shell.ExpandEnvironmentStrings(“%USERPROFILE%”)&”Local SettingsApplication Data”

should take care of finding the right folder – if anybody can confirm that, then add that as a comment to this post.

Bringing up a MESSAGE with the outcome of this function on my machine gives me this dialog:


I don’t know whether that could come in handy, but maybe it can spawn off some good ideas.

Wrapping up

As you can see, you can do a lot of things in VB Script on the Client (or on the Server). There are a number of scripts you can find on the internet to work with the A/D (create, delete and enumerate users).

Of course there a limitations as to what you can do in VBScript and it isn’t a real alternative to writing a COM component, but for something it is easy and straightforward – and it doesn’t require any client side installation of components and this works in both Classic and RTC.

You can download the rename function from ClausL’s post about sending e-mail with PDF attachments. You will need to do copy, paste and maybe modify the other samples in order to use them.



Freddy Kristiansen
PM Architect
Microsoft Dynamics NAV