Advanced test script for PI Web Services

Blog Post created by mhamel Employee on Apr 20, 2012

Hi everyone,


I have decided follow up on my previous post on test PI Web Services using a Powershell script but by using this time the proxy library generated using the metadata returned by the Web Service itself.


If you want to test PI Web Services using other bindings or with more complex parameters, you generally need to write a small application using Visual Studio. As many components are involved during the installation such as configuring the virtual application on the Web Server (IIS), ASP.NET, application pool, web.config, PI SDK, AF SDK, security, etc. or also, other elements can come into the game: questions related to Active Directory forest, domain(s) and workgroup, and the network routes and filters, many things can go wrong. Your testing application cannot be tailored for a "one size fit all" one. It means you will need to re-configure the class(es) needed for communicating with the Web Service and modify the app.config file, and then you will rebuild your application. These steps can be tedious on the long run. I want to propose you an alternative to this by writing your Powershell script which is quick to edit.


You will need Powershell version 2.0 and later to achieve this as we are communicating with Web Services implementing the Windows Communication Foundation (WCF) which was introduced with the .NET Framework 3.5 that is supported with version 2.0. You will also need the C# compiler (csc.exe) installed under your C:\Windows\Microsoft.NET\Framework\v3.5 or C:\Windows\Microsoft.NET\Framework64\v3.5 and the SVCUtil.exe tool which is installed with Visual Studio. If you don`t have Visual Studio installed on the machine you planned to work on, you can easily copy the files under any folder you want. You need to copy the SVCUtil.exe and SVCUtil.exe.config files. Don`t forget to change the path where these files are copied if there are not at their default location. If you use the SVCUtil.exe from the .NET Framework 4.0, you will need to create or modify the powershell.exe.config file under the C:\Windows\System32\WindowsPowerShell\v1.0 folder with the following settings:



By default Powershell is configured to only use .NET Framework 2.0 assemblies, so you need to enable the use of 4.0 ones.


Let`s examine the script in more details... This script contains three (3) functions to be used:

  • PIWS-Https-TestGetPIArchiveData
  • PIWS-NetTCP-TestGetPIArchiveData
  • PIWS-RawXMLSOAP-TestGetPIArchiveData

The first two: PIWS-Https-TestGetPIArchiveData and PIWS-NetTCP-TestGetPIArchiveData make use of a proxy DLL which is dynamically compiled and added to the script to send request to PI Web Services, the last one is the function I introduced in my last blog entry regarding manually creating a SOAP/XML message to invoke PI Web Services methods.


Let start by explaining the logic of this script for functions: PIWS-Https-TestGetPIArchiveData and PIWS-NetTCP-TestGetPIArchiveData. First, you need to generate a proxy DLL representing the classes used by the Web Service, followed by loading it into Powershell namespace using the principle of reflection. You will need to create an instance of a class representing one of the services offered by PI Web Services (either PITimeSeries or PISearch); thereafter this instance is called your proxy object. It is important to configure the impersonation level used by the Powershell script.

#Allow delegation to occur.
$_Proxy.ClientCredentials.Windows.AllowedImpersonationLevel = [System.Security.Principal.TokenImpersonationLevel]::Delegation

In many cases, you will use a delegation level to enable your credentials to be passed between two machines. Finally, you will manipulate your proxy object and some classes to launch request against the different Web methods


Generating a Proxy
This step consists of calling the SVCUtil.exe command with the endpoint to generate two (2) files which will contain class definitions and the default app.config. Both files will be copied in the same folder of your Powershell script. Secondly, the CSC.exe command is called with the classes definition file to compile into an assembly file (*.dll). The AnyCPU platform is selected for compilation. If you are interested to know what command lines are invoked, I suggest you take a look in the script file attached at the end of this blog entry.




Loading the Generated Assembly
This step consists of loading the generated assembly file (*.dll), and two (2) other ones in the Powershell session namespace by the use of Reflection.Assembly.LoadFrom method. The System.ServiceModel and System.Security.Principal namespaces are loaded for their usage in the script. If you want to make use of the .config file generated, you have to invoke the CurrentDomain.SetData method with the path of the file before calling the Reflection.AssemblyLoadFrom method, otherwise it won`t be taken into account.

#Add the configuration file into the domain before loading the assembly if using default...
if ($Configuration -eq "default") { [System.AppDomain]::CurrentDomain.SetData("APP_CONFIG_FILE", $WSLibPath + ".config") }
#Add a reference to the PISDK assembly.
[reflection.assembly]::LoadFrom($WSLibPath) | Out-Null
#Add a reference to the servicemodel.
[Reflection.Assembly]::LoadWithPartialName("System.ServiceModel") | Out-Null
#Add a reference to ...
[Reflection.Assembly]::LoadWithPartialName("System.Security.Principal") | Out-Null

This step consists of creating a proxy client object representing your connection with the Web Service. You can invoke one of its constructors that takes the name of the endpoint as argument. The other allows defining a custom configuration that you can control programmatically.




Build your Request
This step looks like what you would do if you were using Visual Studio. You create your requests and send them to the GetPIArchiveData method which will return an array of TimeSeries object that you can manipulate.




To utilize your script, you will need to open a command prompt and call powershell or call powershell directly from the Run command. As a very important step, you will need to unlock the policy for using this type of script by invoking this command: Set-ExecutionPolicy RemoteSigned at the Powershell prompt. Afterward, you can invoke your script wherever you saved it by simply typing its full path and name. If you receive errors directly inside the Powershell session, it means something is not configured properly somewhere. Otherwise in case of success you will receive a screen that looks like the following.


If you are using PI Web Services 2010 R2 or R3 installed on IIS and using the Net TCP binding, the default port used is 808. You will need to specify the port in the URI of the Web Service.



If you are interested you can also test other bindings such as the name pipes. Although, it works only within the boundary of a unique machine. Try different paths involving PI Data Archive, PI AF or PI Performance Equation.


Please find a copy of the script here. Share some thoughts or comments with me by replying to my blog.