Skip navigation
All Places > PI Developers Club > Blog > Author: Gregor

PI Developers Club

5 Posts authored by: Gregor

Content here


This blog post is inspired by a post titled PI System adoption rate metrics at Generic vCampus Discussions forum but it takes also its root from many questions that we were asked on how someone could identify suspicious connections to PI Server or compare the amount of licensed clients against the actual usage.


When I received this question the first time many years ago, while working at OSIsoft Technical Support, the solution that I suggested was to create a scheduled task that would periodically hit a batch file. The batch file would query PI Network Manager Statistics through the execution of a piconfig.exe script and dump information into a text file. Anyone can think of various solutions for further treatment of data by a custom application or by the usage of Microsoft Excel.


The major disadvantage of this solution is that it only takes a sample at certain times and may miss what has happened between the sampling periods.


Times have changed. With PowerShell, Microsoft has introduced a powerful scripting tool that also supports the usage of .NET objects directly. OSIsoft development was so kind to offer PowerShell Tools for the PI System to the vCampus community; this new tool is building the bridge between PowerShell and the PI System.


I must admit that I am a beginner with PowerShell and don’t yet really feel “comfortable”. During my research I found people praising PowerShell with the highest sounds. Meanwhile I have recognized how it can be easy to do what you want and feel PowerShell has a bright future.


My team mate Mathieu Hamel has created the major part of the solution that we would like to introduce to the vCampus community with this post. While discussing the script concepts and details we recognized potential unexploited areas of PowerShell scripting with the PI System. While reading further to this blog post you might be interested to download and use the project files discussed. Please find them attached to this post or use this link.


As you know, vCampus has a section for community projects. We – the vCampus team – are a little sad that they are not really alive as they could be. We believe that community projects are great and enable a group of individuals and up to the whole community in certain cases to work together to create something that delivers value to the community. Doesn’t that sound great? Doesn’t that sound fun? I couldn’t think of something else delivering a higher social value within a forum.


To get to the point, we believe that PowerShell Tools for the PI System are not only a powerful way of scripting but has the potential for one or more great community projects. We would love to get your opinion about this. Please also let us know what you are interested in but please bear in mind that we don’t just want to serve you with examples. When you suggest something please expect playing an active part if it comes to a community project.


We are enthusiastic about the idea of seeing PI geeks like you more active on community projects with PowerShell Tools for the PI System soon. Hence we have limited the scope of the solution we present here today accordingly. The script is designed to provide basic functionality and leave room for extensibility. It also aims at users who are just interested to test or use it as is without diving into the code. Please document your interest by replying to this blog.








[ Introduction ]     [ Concept ]     [ Solution ]     [ Limitations ]     [ Requirements ]     [ Preparation / Installation ]      [ Usage ]      [ Reports ]      [ FAQ ]      [ Prospect ]










The concept mainly involves the following steps:


- Retrieval of message attributes from source PI Network Manager through PowerShell Tools for the PI System (used cmdlets GET-PIServer Get-PIMessage)
- Looking up the message ID as the first message attribute, comparing it against the “known” ID’s and deciding about further message treatment
- Creation of Custom Objects table in memory
- Refining information using Regular Expressions and storing results as facts into the Custom Objects table
- Exporting these facts into a comma separated file (CSV) or a self describing XML file that can be used to do further analysis in other software such as Microsoft Excel
- [Optional] Do further analysis to generate certain KPI’s and store them in separate comma separated (CSV) files.










[ Introduction ]     [ Concept ]     [ Solution ]     [ Limitations ]     [ Requirements ]     [ Preparation / Installation ]      [ Usage ]      [ Reports ]      [ FAQ ]      [ Prospect ]








The solution consists of the following files and folders:




Folder (1)


Log file target

Folder (2)


Holds the PowerShell module files

Folder (3)


Target folder for results

Folder (4)

\PISystemstats\Unit Tests &  Examples

Holds files that can be used for testing and automation



PISYSSTATS Module Manifest (in Folder 2)



PISYSSTATS Core Library (in Folder 2)


Automatic Debug - Test Unit.bat

Windows Batch to launch “Test Unit.ps1” (In Folder 4)


Test Unit.ps1

Test script

When you apply modifications to the module script, all you need to do is save it and reload the module again in a new PowerShell session. Alternatively you can use Remove-Module followed by Add-Module command to load the modified module script. If you are just interested in using the solution there is no need for editing the module script but we hope many of you are curious enough to at least read through the code. There are a lot of comments intended to make it easier for you to understand what is done within certain functions.


To make the usage easier we have created a Windows Batch file (Automatic Debug - Test Unit.bat) and a test script (Test Unit.ps1). When you are interested to use them, you will have to modify the paths specified inside both files. The Windows Batch file refers to the test Unit script while “Test Unit.ps1” refers the folder where the module files are located (Folder 2).


You will likely have to unblock both PowerShell module files (Folder 2). To do so open Windows file explorer, browse for the module files (\PISystemstats\bin\PISYSSTAT), right click one, select properties and click the [Unblock] button (at the very bottom at the General tab).










[ Introduction ]     [ Concept ]     [ Solution ]     [ Limitations ]     [ Requirements ]     [ Preparation / Installation ]      [ Usage ]      [ Reports ]      [ FAQ ]      [ Prospect ]








Starting with PI Server 3.4.380, structured messages were introduced to the PI Message Log; messages now include fields such as “Message ID”. Hence our example requires PI Server 3.4.380 or later. Please note this is also requirement for PowerShell Tools for PI System.


Because the Message ID is a unique identifier for the kind of message, our example is using to select the pattern of information exposed in the message body.


Furthermore, because the approach is generating statistics based on log messages from PI Network Manager and that PI Network Manager does not log messages about existing connections periodically, we can expect only complete information for those connections that were established after the query period start and closed before the query period ends. Per default (tuning parameter MessageLog_DayLimit) PI Message logs are kept for 35 days only. Please keep this in mind when defining the query period and when interpreting the results.


Connection ID’s are uniquely used within a PI Network Manager session but after a restart PI Network Manager will start over again counting from 0. To avoid confusion we have built in a mimic that recognizes based on connections start- and end-times that PI Network Manager has been restarted. When this happens the index field within the connection facts object is increased by one. All connections with the same index fall into the same period between 2 PI Server restarts (if applicable).


PISYSTATS module may only work against Primary PI Servers in a collective environment. This is due to a bug in PowerShell Tools for the PI System introduced with version (doesn't exist in that will likely be fixed in the next release. I expect this will also allow PISYSTATS to work against Secondary collective members.








[ Introduction ]     [ Concept ]     [ Solution ]     [ Limitations ]     [ Requirements ]     [ Preparation / Installation ]      [ Usage ]      [ Reports ]      [ FAQ ]      [ Prospect ]








For those users new to PowerShell, please read Jay’s blog post about PowerShell Tools for the PI System


- Windows PowerShell is supported on Windows XP, Windows Server 2003, Windows Vista, Windows Server 2008, Windows 7, Windows Server 2008 R2, Windows 8 and Windows Server 2012. Please note: While recent Windows versions such as Windows 2012 Server ship with Windows PowerShell included, it has to be installed separately on older Windows platforms such as Windows XP.
- Windows PowerShell 2.0 or later
- PowerShell Tools for the PI System or greater








[ Introduction ]     [ Concept ]     [ Solution ]     [ Limitations ]     [ Requirements ]     [ Preparation / Installation ]      [ Usage ]      [ Reports ]      [ FAQ ]      [ Prospect ]







Preparation / Installation

Some of the following steps may be obvious for experienced PowerShell users but may puzzle one or the other user at "beginner" level.


1. Make sure you have Microsoft PowerShell for Windows 2.0 or higher installed ("Add or Remove Programs" / "Programs and Features") on the machine that you would like to use. If this machine is remote to your PI Server, please note that you don't have to install Microsoft PowerShell on your PI Server node.
2. Download and install OSIsoft the recent version of OSIsoft PowerShell Tools for the PI System available exclusively at vCampus Download Center under "Extras".
3. Download and install the package attached to this post. Please create a folder on the target machine (e.g. D:\PIPC\PISystemStats) and paste the content from attached ZIP file into this folder.


We have some additional recommendations you may find useful in particular as well as in general when working with PowerShell, OSIsoft PowerShell Tools for the PI System and PowerShell scripts.


1. Creating a Profile for PowerShell initialization
You may have recognized that after installing OSIsoft PowerShell Tools for the PI System that the belonging cmdlets are not available within new PowerShell sessions until you execute




Add-PSSnapin OSIsoft.Powershell

Things like this can perfectly be automated by creating a Windows PowerShell Profile. Please see e.g. MSDN Library for additional information about the Windows PowerShell Profile.
To create yourself a PowerShell Profile, please create profile.ps1 at C:\Users\<username>\Documents\WindowsPowerShell where <username> refers your logon name. Edit, enter above command and save profile.ps1
To verify if it is working, please launch a new PowerShell session and see if you can immediately use the PowerShell Tools for the PI System cmdlets e.g.:





Instead of loading the profile, you may see an error like the following one:


File C:\Users\<username>\Documents\WindowsPowerShell\profile.ps1 cannot be loaded because the execution
of scripts is disabled on this system. Please see "get-help about_signing" for more details.           

At line:1 char:2                                                                                       
+ . <<<<  'C:\Users\<username>\Documents\WindowsPowerShell\profile.ps1'                                
    + CategoryInfo          : NotSpecified: (:) [], PSSecurityException                                
    + FullyQualifiedErrorId : RuntimeException                                                         


The reason for this error is that script execution is disabled by default. Please scroll down to learn how you can enable script execution but before moving on to the next topic you may be interested in how to add the Get-PISystemStats module to your profile. For this purpose you need to provide the path to the PISYSSTATS library and manifest file which depends on where you've extracted the package to. In order to do something new, let's introduce the usage of a PowerShell variable for this purpose. Please add the following to lines to your profile.ps1 file:


$modulePath = "D:\PIPC\PS\bin\PISYSSTAT"
Import-Module $modulePath

Save the changes to disk and launch a new PowerShell session. To see if the profile has loaded properly, you can look for the PISYSTATS help:


Get-Help Get-PISystemStats



2. Enable script execution


There exist several different levels with Script Execution Policy. To see details you could e.g. use


Get-Help Set-ExecutionPolicy

There are again many additional options. I personally like using the online help:


Get-Help Set-ExecutionPolicy -online

For sure this doesn't work with Windows core installations but back to the topic... Our recommendation for setting the execution policy is the following one but you may want to check with your local IT:


Set-ExecutionPolicy RemoteSigned

If you run into any issues, please try if launching PowerShell as Administrator helps. Please feel free to open a thread at Scripting with Windows PowerShell forum for any kind of issues you experience.










[ Introduction ]     [ Concept ]     [ Solution ]     [ Limitations ]     [ Requirements ]     [ Preparation / Installation ]      [ Usage ]      [ Reports ]      [ FAQ ]      [ Prospect ]










At this point we expect you to have the Get-PISystemStats module loaded already. If the following examples do not work for you, please revisit the Preparation / Installation section. If you still see errors, please post them at the Scripting with Windows PowerShell forum.


I would like to start looking at the cmdlets help first what usually is a good idea with PowerShell:


PS C:\Users\Gregor> Get-Help Get-PISystemStats




    This function returns PI System statistics.


    Get-PISystemStats [-ServerName] <String> [-StartTime] <String> [-EndTime <String>] [-OutputMode <Int32>] [-ShowUI <Boolean>] [-DBGLevel <Int32>] [<CommonParameters>]


    This function returns PI System statistics. The Syntax is ...
    Get-PISystemStats ([-ServerName | -sn] <string>)
                      ([-StartTime | -st] <string>)
                      [[-EndTime | -et] <string>]
                      [[-OutputMode | -om] <int>]
                      [[-ShowUI] <boolean>]
                      [[-DBGLevel | -dbgl] <int>]




    To see the examples, type: "get-help Get-PISystemStats -examples".
    For more information, type: "get-help Get-PISystemStats -detailed".
    For technical information, type: "get-help Get-PISystemStats -full".


You should also try the following and look at the results:


Get-Help Get-PISystemStats -Examples
Get-Help Get-PISystemStats -Detailed
Get-Help Get-PISystemStats -Online

The link to the online help directs you to this thread that we will add a link to this blog to as soon as it is published. You may have to sign in with your SSO account but isn't that cool?


Ok, let's calm down and continue discussing the cmdlets parameters:








Name of the PI Server




Period start




Period end




Report type definition




Show output No / Yes




Debug Level

The -ServerName parameter is required and specifies the PI Server to retrieve the messages from. It's also valid to use the name of a Collective but the connection will always go to the Primary because of a bug in PowerShell Tools for the PI System.


Messages from PI Network Manager will be retrieved for the period specified by -StartTime and -EndTime. PI Server time format is used e.g. "*-1d", "*" and "10-Apr-2013 12:23"


The -OutputMode parameter is optional and can be used to specify how PISYSSTATS treats and aggregates results.


- 0 (default) manipulate internally the facts table; will generate up to 5 different reports in CSV format (Application Stats.csv, Applications.csv, IP Addresses.csv, Total Connections during uptime.csv and Trusts.csv).
- 1 will export the facts table in CSV format (connectionfacts.csv).
- 2 will export the facts table in XML format (connectionfacts.xml) including schema and data. 


With -ShowUI one can control if PISYSTATS generates a prompt ($true default) or not ($false). This parameter is useful when running Get-PISystemStats as a scheduled task. With ShowUI enabled PISYSTATS will display its progress and finally output to the prompt where reports have been generated.


Process PI Log messages 
    402 / 654             


With -DbgLevel  = 0 (default) only none verbose messages are logged. This is mainly Start and End of cmdlet execution. 1 is for showing warnings and internal messages, 2 for showing parsing results and internal variables


We found it useful using the combination of a batch file and a PowerShell script file for testing purposes. Another possible use case would be when scheduling PISYSSTATS together with one or more other tasks. Hence we enclosed the "Unit Tests & Examples" folder and it's content into our delivery. Before executing "Automatic Debug - Test Unit.bat" for the first time, please review the content and modify the path to "Test Unit.ps1" if necessary. 


REM 64 bit
powershell -NoLogo -ExecutionPolicy RemoteSigned -WindowStyle Normal -NoExit -File "C:\DevProjects\PISYSSTAT\v1.0.0.8\Unit Tests & Examples\Test Unit.ps1"

Please note that the batch executes PoweShell with ExecutionPolicy set to RemoteSigned. The changed execution policy only lives inside the session launched by the batch. It is not persistent.


Please also review the path to "PISYSSTAT.psd1" and "PISYSSTAT.psm1" within "Test Unit.ps1" as well as the name of your PI Server node (here core-tex).


# Import the module
$modulePath = "C:\DevProjects\PISYSSTAT\v1.0.0.8\bin\PISYSSTAT"
Import-Module $modulePath

# See all available cmdlets
#Get-Command -Module "PISYSSTAT"

#Get-Help Get-PISystemStats -full
Get-PISystemStats "core-tex" "*-5d" -om 1 -dbgl 0







[ Introduction ]     [ Concept ]     [ Solution ]     [ Limitations ]     [ Requirements ]     [ Preparation / Installation ]      [ Usage ]      [ Reports ]      [ FAQ ]      [ Prospect ]








Except when executing Get-PISystemStats in silent mode (-ShowUI $false), the path to reports will show at the command prompt e.g.


The export process is completed. See the generated files under the folder: C:\DevProjects\PISYSSTAT\v1.0.0.8\Export\20130821_151611


Please note that the date and time is coded to the folder's name that is generated for a specific execution. You will find the resulting reports within that folder. What content you'll find depends on the selected OutputMode. I would have loved sharing an example of the connectionfacts report and to discuss some of the details but even after hiding several cells, there are by far too much to fit into the blog post format. The table is to wide to fit and the majority of the columns become cut. Just explaining the single columns doesn't appear necessary since my believe is that the headers are self explaining.








[ Introduction ]     [ Concept ]     [ Solution ]     [ Limitations ]     [ Requirements ]     [ Preparation / Installation ]      [ Usage ]      [ Reports ]      [ FAQ ]      [ Prospect ]







Frequently Asked Questions

As just said, I expect reports are being self explaining but you may have one or the other question. I'll try to answer the ones that I expect to come and reserve the freedom to add more later.

Q1: I see complete information for some connections but incomplete information for others. Why is this?

This is one of the limitations mentioned above. PI Network Manager recognizes incoming connection attempts, successful attempts and if a connection becomes closed. When reporting these messages to the PI Message Log on the PI Server, it uses different messages that have unique message ID's and contain certain kind of information. When we query the PI Message Log we need to specify a period by StartTime and EndTime. This introduces the risk to exclude related messages and the information they contain. This said, we pretty likely miss information that was logged before StartTime and after EndTime. This is also valid for connections that are currently alive when specifying EndTime with '*'.

Q2: Connectionfacts report contains an "Index" field that I couldn't locate in any of the messages from PI Network Manager. What is this about?

PI Network Manager counts connections as ID. It starts to count with 1 with the first incoming connection after PI Network Manager service start. With other words, if a PI Server is re-started for some reason, PI Network Manager will recycle connection ID's. To avoid information before and after a restart becomes confused, we introduced the 'Index' column that starts counting with 0 and is increased by 1 every time PI Network Manager reports that it just has been started. You can consider all information with the same Index belonging together while the same connection ID showing with a higher Index indicates PI Network Manager has been restarted. Since almost all PI Services have a service dependency on PI Network Manager you can easily consider a PI Network Manager restart a restart of the PI Server but not necessarily a reboot of the PI Server node.








[ Introduction ]     [ Concept ]     [ Solution ]     [ Limitations ]     [ Requirements ]     [ Preparation / Installation ]      [ Usage ]      [ Reports ]      [ FAQ ]      [ Prospect ]










Have you tried PISYSTATS already? What information / report do you find valuable? Is it contained in one of the specific reports (OutputMode=0) or within the Connectionfacts (OutputMode 1 and 2)? If it's in the Connectionfacts, what's your idea of further refining (using Excel, enhancing PISYSTATS or other e.g. using the XML Connectionfacts report)? 




We are curiously looking forward to your feedback and encourage you to develop the "project" by introducing new functionality i.e. reports. When you do so we would appreciate you share your "stuff" with the community. Hence, please introduce a new OutputMode when implementing your own treatment of information. 




We also encourage you exploring the abilities and the power of PowerShell and PowerShell Tools for the PI System. This is cool stuff with a bright future! Why waiting for the future? Let's make it happen now!


[ Introduction ]     [ Concept ]     [ Solution ]     [ Limitations ]     [ Requirements ]     [ Preparation / Installation ]      [ Usage ]      [ Reports ]      [ FAQ ]      [ Prospect ]

How to deal with PI Message Logs




You are facing an issue with your PI System, a PI Client or a PI Interface? You like to understand why things are not working as expected? Does PI tell you what's going on? E.g. why PI ProcessBook running on your client machine isn't able to connect to your remote PI System?


Yes, it does! This post is intended to help you dealing with PI Message Logs.


Please also pay attention to OSIsoft KB Article # 3248OSI8 and the belonging video at Youtube.


1.       Logging in PI


The most relevant log when working with PI is the PI Message Log. In this post I will focus on PI Message Logs but first let's take a look at the available logs:


1.1   pipc.log


The pipc.log is the traditional log file being used by PI API based applications like PI ProcessBook earlier than version 3.x and Interfaces to the PI System. UNIINT (a framework for OSIsoft Interfaces to the PI System) based interfaces compiled against UNIINT versions later than 4.5.x are logging to the PI Message Log. If and what UNIINT version was used can either be verified with the Interface manual belonging to a particular interface release or within the PI Interface Configuration Utility (ICU). When an interface (instance) configuration is loaded into the ICU the UNIINT version is displayed below the configuration ComboBox.


With PIPC Log Migration enabled (Migratelog=1 in pipc.ini) all pipc.log messages will be forwarded to the PI Message Log.


The PIPC Log Server service maintains (shifts, recycles) the pipc.log files and uses settings provided with pipc.ini (e.g. MAXPIPCLOGS and MAXLOGSIZE)


PIPC.log files are pure text format and can be read with editors like notepad.exe


Using a 3rd party editor that supports syntax highlighting is reasonable.


The pipc.log is being replaced with the PI Message Log over time.


1.2   PI Message Log


File names of the PI Message Log (aka PI Server Log or PI SDK Log) are pimsg_*.dat where * is for a 7 digits number that represents the start date of the particular log file. E.g. pimsg_1120731.dat is from 31-Jul-2012. PI Message Logs are of binary format and usually opened exclusively by PI Message Subsystem service.


On a PI Server, PI Message Log files are located in the PI\Log folder; on clients and interfaced nodes, also called PINS nodes, the folder is PIPC\Log.


The PI Message Log is the most important log these days when working with PI System products.  


In case PI Message Subsystem service is down or unresponsive, messages are sent to the Windows Application Event log. As soon as PI Message Subsystem becomes responsive again it migrates (but does not move) messages from Windows Application Event Log into the PI Message Log.


PI Message Logs expire after 35 days. This is controlled and configurable by the tuning parameter MessageLog_DayLimit, introduced with PI SDK (PI Server 3.4.380 SP1 and 2010 SP1). Starting PI SDK some tuning parameters are supported on PINS nodes. Piconfig.exe is used maintaining local tuning parameters.


1.3   PI SDK trace logs


PI SDK tracing can be used to log additional information about PI SDK calls. AboutPI SDK.exe (PI SDK earlier than version 1.4.0) or PISDKUtility.exe (since PI SDK 1.4.0) can be used to enable the tracing.


You may be asked to enable tracing and to send the resulting files for analysis when troubleshooting an issue with OSIsoft TechSupport.


1.4   Windows Event Logs


Application failures such as a crash of a PI Subsystem will cause a corresponding failure being logged into the Windows Application Event Log.


Sometimes we find related messages in the Windows System Event Log.


I usually do also request the Windows Security Event Log but don't remember a single case it provided any additional insights.


Some OSIsoft products maintain their own Windows Event Log like the PI Asset Framework (AF).


2.       What are the tools for PI Message Log analysis?


2.1   PI System Management Tools "Message Logs" plug-in


PI System Management Tools setup is included into the PI Server setup kit but available as a separate setup too. It can be installed on PI client machines and PI interface nodes.


The "Message Logs" plug-in (Operation -> Message Logs) is a Graphical User Interface similar to Windows Event Viewer (eventvwr.msc). It expects a start- and end-time definition. Logs can be filtered by severity, source and strings that may show in the message body. Resulting log messages are displayed in a table and additional info is displayed for the selected entry. All or just selected messages can be exported as comma separated, XML, text or rich text format file.




2.2   The pigetmsg.exe command line utility


It's time now outing myself as a command line addict. When using pigetmsg.exe for message retrieval a connection to PI Message Subsystem is established for communication. This does not only work locally but also over the network. Supported protocols are Explicit Login, PI Trusts and Windows Integrated Security (WIS).


An OSIsoft KB article is in preparation about tips and tricks related to PI Message Logs. I plan adding a link ones this KB article is posted.


2.3   PISDKUtility.exe


A new utility that ships starting PI SDK 1.4.0 is PISDKUtility.exe


It's capable of displaying the local message log




3.       Pigetmsg.exe usage - examples


The upcoming PI Server 2012 release includes several improvements to pigetmsg.exe. E.g. it will be possible to only output selected fields and message parameters.  Another new feature will be  the ability to create summary reports for specified message parameters. Please be sure visiting checking out pigetmsg.exe help after installing PI 2012.


I will only discuss those command line switches that I experienced being useful. Depending on the use case other existing switches may turn out being useful too. Hence I encourage you to check the command help for complete list and additional information about existing switches.


pigetmsg -?




pigetmsg -h


Combinations of command line switches as used in the following examples are possible.


3.1   Looking at the PI Message Log continuously


This is the recommendation being used whenever possible e.g. at PI System startup or when verifying an incoming connection attempt.


 pigetmsg -f


3.2   Setting time limitations for message retrieval


Usually we like to look at messages for a period of time specified by start- and end-time. PI Time format is used.


pigetmsg -st *-2h -et *


pigetmsg -st "31-Aug-2012 13:00" -et "01-Sep-2012 10:00"


pigetmsg -st "04-Sep-2012 13:00:01.001" -et *


pigetmsg.exe command line utility expects either looking at logs continuously (option -f), specifying a period by start-time (-st) and end-time (-et) or defining the count of recent messages (-t)


3.3   Redirecting messages into text files


When testing above examples you will recognize messages are passing by in the command prompt quickly and when scrolling back up you may recognize the command line buffer became exceeded. So better to dump messages into a text file:


pigetmsg -st *-2h -et * > C:\Temp\mypimessagelog.txt




pigetmsg -st *-2h -et * -of C:\temp\mypimessagelog.txt


3.4   Filter messages by severity


There are 4 different severity levels with PI Message Logs. The pigetmsg.exe command line tool allows filtering by specifying the minimum severity level.

  • - Debug <= this is the default
  • - Information (-si)
  • - Warning (-sw)
  • - Error (-se)
  • - Critical (-sc)

Most messages are of type Debug or Informational. Filtering them usually means reducing the amount of messages dramatically:


pigetmsg -sw -st *-2h -et *


You may want to take note of the time(s) for severe messages and check the PI Message Log for related information around that time.


3.5   Output formatting


If you prefer using a comma separated format (CSV) e.g. for the analysis with Microsoft Excel, you may find this option useful:


pigetmsg -fc -st *-2h -et *


To force having at least 2 lines for each message log entry, what as far as I've seen is the default, please use the following:


pigetmsg -ft -st *-2h -et *


The wide output format with just one line per message can be forced using:


pigetmsg -fw -st *-2h -et *


Programmers may like the option having messages in XML format:


pigetmsg -fx -st *-2h -et *


3.6   Output all message fields


By default only the most common message fields are shown.


The result when using the -oa switch will include all fields


pigetmsg -oa -st *-2h -et *


I have used CSV format to verify the field names

Column name




















PID (process ID)
















Please note that information fitting in one of the fields listed above may be included into the message body. It will only show up in the corresponding column if it has been explicitly logged to that column.


3.7   Filter by message source / process name


Valid message sources / process names are e.g. pibasess, pinetmgr, pilicmgr, piarchss and pisnapss.


If you are unsure, consult an existing log e.g. using PI-SMT "Message Log" plug-in. Results of the following commands are the same.


pigetmsg -src PIACEClassLibraryHost -st *-2h -et *


pigetmsg -pr PIACEClassLibraryHost -st *-2h -et *


3.8   Filter the message body by a specific string


This is one of the most powerful options if you know what you are looking for e.g. messages regarding a particular PINS node identified by name, FQDN or IP address. An asterisk (*) is the wildcard for multiple characters and a question mark (?) replaces just a single character.


a) Filtering by IP address


pigetmsg -msg ** -st *-2h -et *


b) Filtering by point ID:


It depends how point ID's are referred to. Sometimes we see only "ID: <ptid>" what may confuse with connection ID's


pigetmsg -msg *point ID: 995* -st *-2h -et *


On a large PI System there might be multiple tags with point ID's starting with 995. Hence you may want to make the search string a little stronger by adding a trailing blank:


pigetmsg -msg *point ID: 995 * -st *-2h -et *


 c) Filtering by connection ID:


To filter e.g. a PI Server's log for messages generated for a particular connection, one can look up the connection ID in PI Network Manager Statistics and use it to filter the message body.


 pigetmsg -msg *ID: 234* -st *-2h -et *


d) Filtering for PI error numbers


PI Error messages are represented by negative error code numbers. These error codes do usually show enclosed into square brackets and are of 3 to 5 digits in length. Some examples:

Error #



Record Not Found (Empty)


PI-Redirector could not get archived data from foreign system


No Record Available for Passed recno

Please see chapter 5 "Looking up error codes" for more information on PI error codes.


One can filter for particular error codes:


pigetmsg -msg *[-11202]* -st *-2h -et *


a little bit more laid-back:


pigetmsg -msg *[-???]* -st *-2h -et *


pigetmsg -msg *[-????]* -st *-2h -et *


pigetmsg -msg *[-?????]* -st *-2h -et *


or totally stress-free:


pigetmsg -msg *[-*]* -st *-2h -et *


e) Filtering for "Errors"


Filtering for typical keywords such as "failure", "failed", "error" ...


pigetmsg -msg *fail* -st *-2h -et *


 3.9   Generate a summarized report sorted by the number of occurrences


This option doesn't return any message details but counts the amount of messages for the specified field and sorts the returned list by the amount of occurrences top to bottom.


pigetmsg -top pr -st *-2h -et *


pigetmsg -top pid -st *-2h -et *


4.       Tools for PI Message Log analysis


Based on the different output formats supported (TXT, CSV, XML), one may want to choose different tools for analysis.


4.1   Analyzing text files (.txt)


My personal preference still is notepad.exe but sometimes, with very unclear logs filled up by an almost uncountable amount of sources, I wish I would have a more comfortable tool.


I know there are text editors that support syntax highlighting but I never spent the time checking which one may fit my requirements. If you have any recommendation for me, please don't hesitate answering to this post.


Notepad.exe find function allows you to search for keywords that you have evaluated being useful like "error", "fail", "[- " and so on.


If I am more interested in recent messages than in how things have developed over time, I am using the [Find...] functionality bottom up.


When analyzing my first message log I started reading at the top and was wondering if I would be able to finish through the log before the end of the day. Seeing the same kind of messages, repeating again and again turned out being boring lecture. Before finishing the first page, I started scrolling through the log using the down arrow on my keyboard. Whenever I recognized a change in pattern, I stopped scrolling and looked more detailed. At least for me this method is working and it's one reason why I prefer pure text files above other options.


4.2   Analyzing comma separated files (CSV)


You may like loading comma separated logs into Microsoft Excel and using Filter and / or Conditional Formatting. I can also imagine one or the other may use VBA code for automated searches or aggregation of messages suspected being serious.


4.3   Analyzing XML files


XML files are somehow like very basic databases with each value being enclosed into a field tag. I am curious about your suggestions on what tools can be used for PI Message Log analysis when working with XML format.


5.       Looking up error codes


If an error code shows in PI Message Log and you are unsure what it is about you can use different tools to lookup the translation of a particular error code.


5.1   AboutPI-SDK.exe / PISDKUtility.exe


Starting with PI SDK 1.4.0, AboutPI-SDK.exe utility is replaced with PISDKUtility.exe




As you can see in above screenshot, not only PI Error codes are supported.


Error codes can be decimal or hexadecimal. PISDKUtility.exe displays both but sometimes the logs have error codes supposed being hexadecimal but without the leading "0x" e.g. 80004005. In case the utility returns "Unknown System Error" you may want to try adding the leading "0x" (0x80004005).


5.2   Command line tool pidiag.exe


Alternatively pidiag.exe can be used for the translation of error codes. Some examples:


D:\PI\Adm>pidiag -e 64


[64] The specified network name is no longer available.


D:\PI\Adm>pidiag -e -11057


[-11057] Not Enough Values For Calculation


6.       General considerations


PI Message Logs can grow large. I have seen log files with up to 100 MB on large PI Systems and interface nodes with several instances of different interfaces. For sure 100 MB is by far more than what can be reviewed on a daily basis. I recommend using enhanced debugging options only in case of an issue that requires investigation.


Especially when dealing with multiple interfaces instances of the same type on a single machine, it becomes important to name instances in order to have useful information being logged. The ICU creates a name for each new interface instance added. You may want to make interface names unique e.g. by adding a few letters that help you to identify the source. Please verify after installing new interface instances that the PI Message Log (or pipc.log with interfaces using UNIINT < 4.5.x) clearly identifies what instance has written particular messages.


7.       Final comments


Dealing with logs isn't an easy business but it is not rocket science. If you know your tools, it becomes easy.


Whenever you are facing issues related to PI products, please do not hesitate to contact OSIsoft TechSupport. The same applies if you are unsure if a particular message is indicating a serious issue or not.  


I plan enhancing this post over time by adding information e.g. about using "PowerShell Tools for the PI System" for log file analysis. A colleague recently gave me a hint on using Microsoft LogParser that allows using SQL-like syntax to query all sort of files. Besides PowerShell it looks like another tool for powerful and effective log file analysis. Currently, I am curious what's possible.    


I hope you like this post and maybe you learned a few things that will be of use for you in the future. I am looking forward to receiving your feedback.





1.       Introduction


PI Advanced Computing Engine (PI ACE) is designed for users with basic programming knowledge. Most calculations can be done within the ACECalculations() routine. Even code that has been debugged and found to be generally working may fail or not always deliver the expected results. Troubleshooting timing issues or dependencies from previous events using debugging can be painful and may not help at all understanding runtime failures. Hence one requires convenient methods to allow capturing and logging information during runtime. This is where the LogPIACEMessage() method from OSIsoft.PI.ACE.PIACEBIFunctions class comes into play.



2.       A word of caution and recommendation on logging


On large systems there may be a lot of log messages. Please only turn on logging when required i.e. for testing and debugging purposes and turn it off at other times. Logging slows down performance. This is because there are additional tasks to perform but without logging we are lost in understanding what's going on. This becomes more and more important an increasing number and increasing complexity of calculations.



3.       Log levels


LogPIACEMessage() supports 7 different log levels. 6 of them can be switched on and off per PI ACE Manager for a specific Context during runtime. There is no need for recompilation or for re-starting the related PI ACE Module. Not all of the existing log levels are considered relevant for the usage within your PI ACE code, meaning that levels considered not relevant are used by PI ACE to provide additional information when enabled.


Message type string

Can be switched on and off through PI ACE Manager




No (always on)










User Messages




Counter Information








Calculation Events






4.       Importing  MessageLevel namespace and PIACEBIFunctions class


Since I expect that most users will be using Visual Studio .NET, I am concentrating on this development environment but note that PI ACE logging functionality is also available when using Microsoft Visual Basic 6.


When creating a new PI ACE Module, the PI ACE Wizard creates a new VB .NET library project, adds a reference to OSIsoft.PIACENet library, and imports the OSI.PIACE namespace.


The first thing that I recommend to do within a new PI ACE project is importing the MessageLevel namespace and the PIACEBIFunctions class.



Imports OSIsoft.PI.ACE.PIACEBIFunctions
Imports OSIsoft.PI.ACE.MessageLevel



This is not a mandatory step but helps keeping code lines short and having a clear view to your project. The following code snippet is without the import:





PIACEBIFunctions.LogPIACEMessage(OSIsoft.PI.ACE.MessageLevel.mlErrors, ex.Message, Me.Name)



With the recommended imports it looks like this:





LogPIACEMessage(mlErrors, ex.Message, Me.Name)



5.       Exception handling


Exception handling is very easy with Visual Studio .NET. I strongly recommend using it. After all I like to know why my code is failing and control output behavior on error:





    Public Overrides Sub ACECalculations()
            '* Place your ACE code here *
        Catch ex As Exception
            LogPIACEMessage(mlErrors, ex.Message, Me.Name)
        End Try
    End Sub



Without using the above code snippet exceptions will be handled but the PI Message Log will only contain "Error" messages about the failing module and may not tell me enough information to troubleshoot the failure.


Another good practice is disabling ACE outputs when we don't want "Calc failed" written to the output tags. If ACE outputs are not disabled, "Calc failed" will be written to outputs by ACE when no values are written to them by the ACE calculation logic, possibly due to the code failing. So let's enhance above example accordingly.





    Public Overrides Sub ACECalculations()
            '* Place your ACE code here *
        Catch ex As Exception
            SendDataToPI = False
            LogPIACEMessage(mlErrors, ex.Message, Me.Name)
        End Try
    End Sub



6.       Creating custom messages -  some examples


Besides mlErrors to capture exceptions, one may use mlWarnings and mlUserMessage.



6.1   Example Warning: Input out of range


Let's assume an input is supposed to be between 0 and 200. By switching on Warnings, I like to see when the limits exceed.



If Input.Value < 0 Or Input.Value > 200 Then
       LogPIACEMessage(mlWarnings, "Input out of range (0..200): " & Input.Value.ToString(), Me.Name)
End If



6.2   Example Warning: Input hasn't received any update in the past 10 minutes


If the Input of my ACE calculation hasn't updated for a while, I like to see a corresponding Warning in the PI Message Log (with Warnings switched on for the Context). This example requires either a clock scheduled calculation or another input being the trigger in case natural scheduling is configured. Because we are dealing with PI Times I have added a reference to OSIsoft.PITimeServer library and the corresponding import: 



Imports PITimeServer

Dim prevTime As PITime
Dim timeDiff As Double
prevTime = Input.PrevEvent
timeDiff = ExeTime - prevTime.UTCSeconds
If (timeDiff > 600) Then
       Dim sLog As String
       sLog = "Input has not updated for more than 10 minutes" & vbCrLf
       sLog = sLog & "Last update at: " & prevTime.LocalDate.ToString()
       LogPIACEMessage(mlWarnings, sLog, Me.Name)
End If



6.3   Example User Message: Logging of values and Timestamps



This time I like to calculate the average of the 10 most recent events for the Input and write the result to the Output. This allows me seeing values and timestamps in the log, comparing them against archived values and validating results. Whenever I believe logging is necessary, I can enable User Messages for the corresponding Context in PI ACE Manager.



Dim sLog As String = vbCrLf
Dim inpTime As New PITime
Dim inpValue As Double
Dim outValue As Double = 0
Dim iLoop As Integer
For iLoop = 1 To 10
       inpValue = Input.PrevVal(inpTime)
       outValue += inpValue
       inpTime = Input.PrevEvent(inpTime)
       sLog = sLog & iLoop.ToString() & " - value: " & inpValue.ToString()
       sLog = sLog & " at " & inpTime.LocalDate.ToString() & vbCrLf
Output.Value = outValue / 10
sLog = sLog & vbCrLf & "Result: " & Output.Value.ToString() & vbCrLf
LogPIACEMessage(mlUserMessage, sLog, Me.Name)



7.       Maintaining PI ACE logging in PI ACE Manager

  • Launch PI ACE Manager

  • Browse to the ACE Context level (expand Server -> Scheduler -> Library -> Module -> Context)

  • Right click the context and select "Message Log Level ..."


  • Setting Message Log Level


  • Confirm by clicking [OK]

A change in log level will be reported in the PI Message Log as follows:


I 31-Aug-12 11:32:47 PIACEClassLibraryHost                                                                          (0)
 >> ACEDebug: Set message log level for ACE Context NEMESIS\ACEDebug\ACEClassDebug\\\NEMESIS\ACE\Debugging to 65






8.       Looking into the PI Message Log


We recommend using pigetmsg.exe on the PI ACE Server to monitor the PI Message Log continuously (pigetmsg -f) when working with PI ACE (developing Modules, maintaining ACE using PI ACE Manager).


Especially on larger systems with multiple ACE modules running the amount of messages may be confusing because there are many messages being logged at the same time causing the command prompt scrolling fast what makes it difficult seeing messages that are related to what one is currently working at.


I will write some guidance on effectively analyzing the PI Message Logs in a later blog post - stay tuned.


There are multiple options to filter messages with the pigetmsg.exe command line utility. One of the most useful ones is filtering by the Process ID:




Please note that each time an ACE Module is started a new process ID is assigned to the PIACEClassLibraryHost.exe process. Be sure using the current process ID






9.       Logging to a PI Tag


You may like the idea logging debug information to a PI tag. When doing so, please use a tag of type Digital and a correspondent Digital State Set whenever possible. It is possible using tags of string data types as well but please keep in mind that string tags consume a lot of space in archives because each single character will require one byte. If you decide to use string tags for debugging purpose, please consider setting the archiving tag attribute to 0 (off). Whenever necessary you can set it back to 1 (on) temporarily. Setting archiving to off means that no historical data events will be recorded in the PI Data Archive and only the latest value will be available


The following example is meant to be complementary to the one provided with 6.1 "Example Warning: Input out of range" and 6.2 "Example Warning: Input hasn't received any update in the past 10 minutes". The output tag referred to with Alias "Debug" is of type Digital and has the "SYSTEM" Digital State Set assigned. In case the input drops below zero, "Under Range" will be reported. In case the output goes above 200, we will recognize "Over Range". When the current snapshot is neither under range nor over range we check if it might be older than 10 minutes (600 seconds) and if it is status "Unit Down" will be reported by the debug tag. "Debug" will report "Good" status in case of good "Input".





    Public Overrides Sub ACECalculations()
            If Input.Value < 0 Then
                Debug.Value = Debug.StateNo("Under Range")
            ElseIf Input.Value > 200 Then
                Debug.Value = Debug.StateNo("Over Range")
                Dim prevTime As PITime
                Dim timeDiff As Double
                prevTime = Input.PrevEvent
                timeDiff = ExeTime - prevTime.UTCSeconds
                If (timeDiff > 600) Then
                    Debug.Value = Debug.StateNo("Unit Down")
                    Debug.Value = Debug.StateNo("Good")
                    output.Value = Math.Sqrt(2) * Input.Value
                End If
            End If
        Catch ex As Exception
            SendDataToPI = False
            LogPIACEMessage(mlErrors, ex.Message, Me.Name)
        End Try
    End Sub



10.   A complete example


Finally please find the complete code of example 9. "Logging to a PI Tag" for your reference:





Imports OSIsoft.PI.ACE
Imports OSIsoft.PI.ACE.PIACEBIFunctions
Imports OSIsoft.PI.ACE.MessageLevel
Imports PITimeServer

Public Class ACEClassDebug
    Inherits PIACENetClassModule
    Private output As PIACEPoint
    Private Input As PIACEPoint
    Private Debug As PIACEPoint
    '      Tag Name/VB Variable Name Correspondence Table
    ' Tag Name                                VB Variable Name
    ' ------------------------------------------------------------
       ' Debug                                   Debug
       ' Input                                   Input
       ' output                                  output

    Public Overrides Sub ACECalculations()
            If Input.Value < 0 Then
                Debug.Value = Debug.StateNo("Under Range")
            ElseIf Input.Value > 200 Then
                Debug.Value = Debug.StateNo("Over Range")
                Dim prevTime As PITime
                Dim timeDiff As Double
                prevTime = Input.PrevEvent
                timeDiff = ExeTime - prevTime.UTCSeconds
                If (timeDiff > 600) Then
                    Debug.Value = Debug.StateNo("Unit Down")
                    Debug.Value = Debug.StateNo("Good")
                    output.Value = Math.Sqrt(2) * Input.Value
                End If
            End If
        Catch ex As Exception
            SendDataToPI = False
            LogPIACEMessage(mlErrors, ex.Message, Me.Name)
        End Try
    End Sub
    Protected Overrides Sub InitializePIACEPoints()
              Debug = GetPIACEPoint("Debug")
              Input = GetPIACEPoint("Input")
              output = GetPIACEPoint("output")
    End Sub
    ' User-written module dependent initialization code
    Protected Overrides Sub ModuleDependentInitialization()
    End Sub
    ' User-written module dependent termination code
    Protected Overrides Sub ModuleDependentTermination()
    End Sub
End Class

When joining the vCampus team 2 weeks, I was looking for something simple to refresh my programming skills. It turned out that porting the PIAsynchStatus Example (see pisdk.chm) from VB6 to VB.Net was challenging enough. I believe the result is a good example for asynchronous PI Data Access. So please allow me using it for my first blog post even there will be nothing new for most of you.




The original example is using a Timer to check for status changes from time to time each 0.5 seconds). The advantage is that this allows checking the progress but my idea was using asynchronous callback instead of the Timer. So I have removed the timer and changed the definition of the routine that is called by the Timer in the original VB 6 example to make it handled (triggered) by the OnStatusChange event fired by the asynchronous GetPoints() call:



    Private Sub asynchevents_OnStatusChange(ByVal NewStatus As CallStatusConstants)


    Private Sub asynchevents_OnStatusChange(ByVal NewStatus As CallStatusConstants) Handles asynchevents.OnStatusChange

Updating a ProgressBar with OnProgressChange() event gave me an issue. The first OnProgressChange() was with 1% and the second with 10%. Afterwards my little application was hanging even after disabling the handler for OnStatusChange(). If you’ve managed using OnProgressChange() succesfully, please let me know how. I decided removing the ProgressBar for now.


The next issue I ran into is the following error when attempting to update a control on Form1 from within asynchevents_OnStatusChange():




InvalidOperationException was unhandled by user code: Cross-thread operation is not valid …




The callback from the asynchronous function call is handled in an additional thread that does not have access to the controls that are handled with the main application thread.


The solution is delegating control updates to a separate sub and invoking methods if needed. The OnStatusChange() sub handles different statuses and delegates control updates to separate subs:

    Private Sub asynchevents_OnStatusChange(ByVal NewStatus As CallStatusConstants) Handles asynchevents.OnStatusChange
        Select Case asynchevents.Status
            Case Is = csInProgress
            Case Is = csComplete
            Case Is = csCancelComplete
            Case Else
        End Select
    End Sub

Let's have a look at ShowInProgress() and the conditional invoke. 

    Private Sub ShowInProgress()
        If Me.InvokeRequired Then
            Me.Invoke(New MethodInvoker(AddressOf ShowInProgress))
                lbStatus.Items.Add("New Status: ... in progress")
            Catch ex As Exception
                lbStatus.Items.Add("ShowProgress: " & ex.Message)
            End Try
        End If
    End Sub

The complete Visual Studio .NET 2010 project is attached to this post. I am excited about your replies espacially about your suggestions for improvements.


Last but not least I like to discuss the where clause that is passed with the GetPoints() call. This is a powerful way searching tags by its attributes. Please review the following examples.


1. Non-case sensitive search for all tags that have a specific character or a sequence of characters at first place of their name:



2. Search for tags that have a specific point source and a specific Location1 value. This query is very useful when one would retrieve all the tags serviced by a specific interface instance:

pointsource='OPC' AND Location1=1

3. Query for all tags having a specific pointtype assigned:


Filter Blog

By date: By tag: