16 Replies Latest reply on Jan 23, 2019 4:31 PM by gregor

    Powershell scripts for PI System maintenance

      Interested in learning about everyones use of Powershell with automating maintenance of their PI Systems.  Very much along the same lines of what Wolfgang started here: 

       

      http://vcampus.osisoft.com/discussion_hall/generic_forums/f/20/p/957/4730.aspx

       

      and here:

       

      http://vcampus.osisoft.com/discussion_hall/generic_forums/f/7/p/948/4727.aspx

       

       

       

      The obvious things like reprocessing archives (expanding to all collective members), copying archives amongst a collective or to a backup store, monitoring archives, services, etc.

       

      If so, would be nice to see some powershell scripts that you are using.  I know Wolfgang must have a few up his sleeve by now.

       

       

       

      OSIsoft can feel free to let us know more about their plans for archive maintenance in PI Server 2012.

        • Re: Powershell scripts for PI System maintenance
          MichaelvdV@Atos

          I did play around with Powershell, and creating cmdlets. I'm convinced this is still a real unexplored area for PI Developers and especially administrators.

           

          The cmdlets I created where fairly simple (getting data out of PI, searching for tags, getting snapshot values, inserting values, etc.). I will see if I can retrieve them.

           

          Could be a nice topic for a blogpost.

            • Re: Powershell scripts for PI System maintenance

              Actually Michael, I think OSIsoft should provide a vCampus exclusive webinar rather than a blog on this topic.

                • Re: Powershell scripts for PI System maintenance
                  MichaelvdV@Atos

                  Ah, thinking 'big'... I like it.

                   

                  Why don't you also post your idea in the Idea's for Webinars topic. I would certainly be in favor.

                    • Re: Powershell scripts for PI System maintenance
                      mhamel

                      I let you see in advance what will be release from the next PI Application Development Course workbook: a dedicated appendix on how to use PowerShell in combination with PI SDK.

                       

                      Let me know if you find this helpful.

                       

                      Appendix A - Use PowerShell in combination with PI SDK

                       

                      Windows PowerShell is a task-based command-line shell and scripting language designed especially for system administration. Built on the .NET Framework, Windows PowerShell helps IT professionals and power users control and automate the administration of the Windows operating system and applications that run on Windows. Built-in Windows PowerShell commands, called commandlets or cmdlets, let you manage the computers in your enterprise from the command line. Sets of cmdlets may be combined together in script, executable, or by instantiating regular .NET classes or WMI/COM Objects.

                       

                      Windows PowerShell also provides a hosting mechanism with which the Windows PowerShell runtime can be embedded inside other applications. These applications then leverage Windows PowerShell functionality to implement certain operations, including those exposed via the graphical interface.

                       

                      Windows PowerShell includes its own extensive, console-based help, similar to man pages in UNIX shells, via the Get-Help cmdlet.

                       

                      For more information on PowerShell, consult this URL: http://technet.microsoft.com/en-us/library/aa973757%28VS.85%29.aspx.

                       

                      The idea here is to load PI SDK assemblies to perform PI-related tasks; this can be done by employing the reflection technique. The following example shows how to reference the PI SDK assembly.

                       
                      [reflection.assembly]::loadwithpartialname("OSIsoft.PISDK") | Out-Null
                      

                      For more information on how to load assembly using the reflection, consult this URL:http://www.dougfinke.com/blog/index.php/2010/08/29/how-to-load-net-assemblies-in-a-powershell-session/.

                       

                      If you want to start using PI SDK in PowerShell you will need to follow these steps:

                       
                      1.         Download PowerShell if it is not already installed. Windows 7 and Windows Server 2008 or 2008 R2 come with PowerShell installed by default;

                      2.        Open PowerShell (e.g., Start > Run > type in PowerShell or Start > Programs > PowerShell);

                       

                      3.         You have to enable the use of scripts because it is forbidden by default. You do this by using the Set-ExecutionPolicy cmdlet as shown below. You may want to read up on Execution Policies afterward and perhaps sign your scripts;

                       
                      Execute Set-ExecutionPolicy RemoteSigned
                      

                       4.         Close PowerShell.

                       

                      5.         With Explorer.exe or in any other manner, create the empty text file %UserProfile%\My Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1 in that path.

                       

                      6.         Add the functions you want such as the ones proposed in this appendix.

                       

                      7.         Save the file;

                       

                      8.         Open PowerShell again and you can now call your functions directly.

                       

                       

                       

                      As a simple example, to get the current (snapshot) value of a point, you can follow the example below. If you are not familiar with the PowerShell syntax, the Syntax Highlights section will guide through the basics.

                       

                      Get current value of a point

                       
                      Get current value of a point
                      function PI-CurrentValue
                      {param ($PIServerName, $MyPointName)
                      
                      # Add a reference to the PISDK assembly.
                      [reflection.assembly]::loadwithpartialname("OSIsoft.PISDK") | Out-Null
                      
                      # Create a new PI SDK object.
                      $_PISDK = New-Object PISDK.PISDKClass
                      
                      # Open a connection with the PI Server specified.
                      $_PIServer = $_PISDK.Servers.Item($PIServerName)
                      
                      # Reference the given Point/Tag.
                      $_MyPoint = $_PIServer.PIPoints.Item($MyPointName)
                      
                      # Invoke the Snapshot method with the given arguments.
                      $_PIValue = $_MyPoint.Data.Snapshot
                      
                      # Verify if the value is a digital state or not.
                      if($_PIValue.Value -is [PISDK.DigitalState])
                      {
                          $_DS = New-Variable PISDK.DigitalSate
                          $_DS = $_PIValue.Value
                          $_Value = $_DS.Name
                      }
                      else
                      {
                          $_Value = $_PIValue.Value.ToString()
                      }
                      
                      # Output the value on the console.
                      Write-Host "Current value for tag:", $MyPointName, "is", $_Value, "at", $_PIValue.TimeStamp.LocalDate.ToString()
                      }
                      

                      Syntax Highlights

                       

                      To help you find out your way with PowerShell, some explanations on the syntax are integrated in this section. As the possibilities are so huge with PowerShell, it was not possible to put some notes on each of topics. Instead, you are invited to visit the URLs proposed in the following references to guide yourself in a world of possibilities with PowerShell.

                       

                       

                       

                      For more information see this site on Microsoft PowerShell Syntax at http://www.computerperformance.co.uk/powershell/index_syntax.htm or http://ss64.com/ps/syntax.html or http://msdn.microsoft.com/en-us/library/aa973757(VS.85).aspx

                       

                       

                       

                      Variables

                       

                      Variables are used for storing data which can be used later in the script. Creating a PowerShell variable consists of putting a dollar sign in front of the name you wish to call the variable.

                       

                      PowerShell has no built-in mechanism for enforcing variable types, for example, string variables can begin with letters or numbers. You can restrict the values a PowerShell variable accepts by preceding it with [int] or [string], for example.

                       
                      [int32]$_MyVariable = 5450
                      

                       Avoid using these reserved keywords for your variables: Break, continue, do, else, elseif, for, foreach, function, filter, in, if, return, switch, until, where and while.

                       

                      Note: Use the backtick (') character to indicate the command continue on the next line. Make sure you do not add an empty space after it or it will be interpreted differently.

                       

                      The backtick is located near the 1 key on US keyboard. Also, the backtick character can be obtained by holding down the Alt key and press 0096.

                       

                      Special Variables

                       

                      Some variables are already defined within the PowerShell context. The following table presents some implicit variables.

                      Variables

                      $_

                      It is the current pipeline object,   used in script blocks, filters, the process clause of functions, the Where-Object,   the foreach-object and the switches.

                      $Args

                      Used in creating functions that   require parameters

                      $host

                      Information about the currently   executing host.

                      $null

                      A null object.

                      $Input

                      Input piped to a function or code   block.

                      $?

                      Contains the success/fail status of   the last statement

                      Arrays

                       

                      To create an empty array you need to use this syntax:

                       
                      $_MyArray = @()
                      

                      If you want a fixed multi-dimensional array, you will use this syntax:

                       
                      $_MyArray = New-Object  'object[,]' 10,20
                      

                      To retrieve an element, specify its number, PowerShell numbers the array elements starting at 0. To return all the elements in an array:

                       
                      $MyArray
                      

                      To return the first element in an array:

                       
                      $MyArray[0]
                      

                       Operators

                       

                      This section shows all operators that can be used to validate mathematical expressions, bitwise expressions, and conditional or comparison expressions. PowerShell is fundamentally case insensitive, so you can use the operator the way you like.

                      Operator Definition

                      #

                      # The hash sign is for comments.

                      +

                      Add.

                      -

                      Subtract.

                      *

                      Multiply.

                      /

                      Divide.

                      %

                      Modulus   (Some call it Modulo) - Means remainder 17 % 5 = 2 Remainder.

                      =

                      Equal.

                      -not

                      Logical   not equal.

                      !

                      Logical   not equal.

                      -band

                      Binary   AND.

                      -bor

                      Binary   OR.

                      -bnot

                      Binary   NOT.

                      -replace

                      Replace.

                      Example:

                      "abcde"   -replace "b","B"

                      -ireplace

                      Case-insensitive   replace.

                      Example:

                      "abcde"   -ireplace "B","3"

                      -creplace

                      Case-sensitive   replace.

                      Example:

                      "abcde"   -creplace "B","3"

                      -and

                      AND.

                      Example:

                      ($a -ge 5   -AND $a -le 15)

                      -or

                      OR.

                      Example:

                      ($a -eq   "A" -OR $a -eq "B")

                      -is

                      IS   type.

                      Example:

                      ($a -is   [int])

                      -isnot

                      IS not   type.

                      Example:

                      ($a -isnot   [int])

                      -as

                      Convert   to type.

                      This   example shows that 1 is treated as a string:

                      1 -as   [string]

                      ..

                      Range   operator.

                      Example:

                      foreach ($i   in 1..10) {$i }

                      &

                      Call   operator.

                      This example   shows that &$a will execute Get-ChildItem:

                      $a =   "Get-ChildItem"

                      &$a

                      .

                      (Dot   followed by a space) Call operator.

                      This   example shows that &$a will execute Get-ChildItem in the current scope:

                      $a =   "Get-ChildItem"

                      . $a

                      .

                      Full   stop for an object property.

                      -F

                      Format   operator.

                      Example:

                      foreach ($p   in Get-Process)

                      {

                      "{0,-15}   has {1,6} handles" -F    $p.processname, $p.Handlecount

                      }

                       

                      Conditional or Comparison Operators

                      Operator

                      -lt

                      Less than.

                      -le

                      Less than or equal to.

                      -gt

                      Greater than.

                      -ge

                      Greater than or equal to.

                      -eq

                      Equal to.

                      -ne

                      Not Equal to.

                      -contains

                      Determine elements in a group. This   always returns Boolean $True or $False.

                      -notcontains

                      Determine excluded elements in a   group. This always returns Boolean $True or $False.

                      -like

                      Uses wildcards for pattern matching.

                      -notlike

                      Uses wildcards for pattern matching.

                      -match

                      Uses regular expressions for   pattern matching.

                      -notmatch

                      Uses regular expressions for   pattern matching.

                      Bitwise

                      -band

                      Bitwise   AND.

                      -bor

                      Bitwise   OR.

                      -is

                      Is of   Type.

                      -isnot

                      Is not   of Type.

                      Other

                      if(condition)

                      If   condition.

                      elseIf(condition)

                      ElseIF.

                      else(condition)

                      Else.

                      Redirect output to a text file.

                      Example:

                      .\cmdlet > stuff.txt

                      >> 

                      Same as Redirect except it appends   to an existing file.

                       

                       

                      Example

                       

                      This section shows functions that interface with the PI SDK library to:

                      • Get snapshot value of a point;
                      • Get snapshot of a point using a pipeline input.
                      • Get archive value of a point;
                      • Get archive value of a point using a pipeline input;
                      • Get archive values of a point for a maximum of n events;
                      • Insert a value for a point at a given time;
                      • Perform a tag search that returns a list of points. This point list can be piped to another function;
                      • Read messages from the PI Message Log.

                      Note: A pipeline is a series of commands connected by pipeline operators (|)(ASCII 124). Each pipeline operator sends the results of the preceding command to the next command. You can use pipelines to send the objects that are output by one command to be used as input to another command for processing. And you can send the output of that command to yet another command. The result is a very powerful command chain or "pipeline" that is comprised of a series of simple commands.

                       

                      Each PowerShell function uses parameters to perform certain tasks. Using the param function assigns all arguments passed to a specific object.

                       

                      To be continued on the next post...

                       

                       

                        • Re: Powershell scripts for PI System maintenance
                          mhamel

                           

                           

                          The continuation of the previous post...

                           

                          The first example returns the snapshot value of a given point. You need to a reference to OSIsoft PI SDK library via reflection. You create and instantiate a PISDKClass object ($_PISDK) to handle the communication with the PI Server as you would do within a standard .NET Framework project. The script continues with opening the connection to the PI Server using the integrated security, referencing the specific point and extracting a PI Value from the Snapshot method. It is important to test if the returned value is a DigitalState object or a standard one. Finally, the value is written to the standard output of PowerShell: the screen.

                           

                           

                           

                          Get snapshot value of a point

                           
                          function PI-CurrentValue
                          {param ($PIServerName, $MyPointName)
                          
                          # Add a reference to the PI SDK assembly.
                          [reflection.assembly]::loadwithpartialname("OSIsoft.PISDK") | Out-Null
                          
                          # Create a new PI SDK object.
                          $_PISDK = New-Object PISDK.PISDKClass
                          
                          # Open a connection with the PI Server specified.
                          $_PIServer = $_PISDK.Servers.Item($PIServerName)
                          
                          # Reference the specified Point/Tag.
                          $_MyPoint = $_PIServer.PIPoints.Item($MyPointName)
                          
                          # Invoke the Snapshot method with the given arguments.
                          $_PIValue = $_MyPoint.Data.Snapshot
                          
                          # Verify if the value is a digital state or not.
                          if($_PIValue.Value -is [PISDK.DigitalState])
                          {
                              $_DS = New-Variable PISDK.DigitalSate
                              $_DS = $_PIValue.Value
                              $_Value = $_DS.Name
                          }
                          else
                          {
                              $_Value = $_PIValue.Value.ToString()
                          }
                          
                          # Output the value to the console.
                          Write-Host "Current value for tag:", $MyPointName, "is", $_Value, "at", $_PIValue.TimeStamp.LocalDate.ToString()
                          }
                          

                           

                           

                          Get archive value of a point

                           
                          function PI-RecordedValue
                          {param ($PIServerName, $MyPointName, $Time, $Mode)
                          
                           # Add a reference to the PI SDK assembly.
                          [reflection.assembly]::loadwithpartialname("OSIsoft.PISDK") | Out-Null
                          [reflection.assembly]::loadwithpartialname("OSIsoft.PISDKCommon") | Out-Null
                          
                          # Create a new PI SDK object.
                          $_PISDK = New-Object PISDK.PISDKClass
                          $_Asynch = New-Object PISDKCommon.PIAsynchStatusClass
                          
                          # Open a connection with the PI Server specified.
                          $_PIServer = $_PISDK.Servers.Item($PIServerName)
                          
                          # Reference the specified Point/Tag.
                          $_MyPoint = $_PIServer.PIPoints.Item($MyPointName)
                          
                          # Validate the extraction mode.
                          $_ModeEnum = 0
                          switch($Mode)
                          {
                              "rtAtOrBefore" {$_ModeEnum = 1}
                              "rtAtOrAfter" {$_ModeEnum = 2}
                              "rtInterpolated" {$_ModeEnum = 3}
                              "rtCompressed" {$_ModeEnum = 4}
                              "rtAuto" {$_ModeEnum = 5}
                              "rtBefore" {$_ModeEnum = 6}
                              "rtAfter" {$_ModeEnum = 7}
                              default {$_ModeEnum = 3}
                          }
                          
                          # Invoke the ArcValue method with the specified arguments.
                          $_PIValue = $_MyPoint.Data.ArcValue($Time, $_ModeEnum, $_Asynch)
                          
                          # Verify if the value is a digital state or not.
                          if($_PIValue.Value -is [PISDK.DigitalState])
                          {
                              $_DS = New-Variable PISDK.DigitalSate
                              $_DS = $_PIValue.Value
                              $_Value = $_DS.Name
                          }
                          else
                          {
                              $_Value = $_PIValue.Value.ToString()
                          }
                          
                          # Output the value to the console.
                          Write-Host "Recorded value for tag:", $MyPointName, "is", $_Value, "at", $_PIValue.TimeStamp.LocalDate.ToString()
                          }
                          

                           

                           

                          Get archive values of a point for a maximum of n events

                           
                          function PI-RecordedValuesByCount
                          {param ($PIServerName, $MyPointName, $StartTime, $Count, $BoundaryType)
                          
                          # Add a reference to the PI SDK assembly.
                          [reflection.assembly]::loadwithpartialname("OSIsoft.PISDK") | Out-Null
                          [reflection.assembly]::loadwithpartialname("OSIsoft.PISDKCommon") | Out-Null
                          
                          # Create a new PI SDK object.
                          $_PISDK = New-Object PISDK.PISDKClass
                          $_Asynch = New-Object PISDKCommon.PIAsynchStatusClass
                          
                          # Open a connection with the specified PI Server.
                          $_PIServer = $_PISDK.Servers.Item($PIServerName)
                          
                          # Reference the specified Point/Tag.
                          $_MyPoint = $_PIServer.PIPoints.Item($MyPointName)
                          
                          # Convert the Count parameter into a declared int32 variable.
                          $_ValuesNeeded = [int32]$Count
                          
                          # Default direction is forward.
                          # If count is a negative value the direction is backward, otherwise
                          # it is forward.
                          $_Direction = 0
                          if($_ValuesNeeded -lt 0) {$_Direction = 1; $_ValuesNeeded = $_ValuesNeeded * -1} else{$_Direction = 0}
                           
                          # Invoke the RecordedValuesByCount method with the specified arguments.
                          $_PIValues = $_MyPoint.Data.RecordedValuesByCount($StartTime, $_ValuesNeeded, `
                                       $_Direction, 0, $null, $null, $_Asynch)
                          
                          # Return the archive Values.
                          Write-Host "Values for tag:", $MyPointName
                          Write-Host "Found ", $_PIValues.Count.ToString(), " values."
                          foreach ($_PIValue in $_PIValues)
                          {
                              # Verify if the value is a digital state or not.
                              if($_PIValue.Value -is [PISDK.DigitalState])
                              {
                                  $_DS = $_PIValue.Value
                                  $_Value = $_DS.Name
                              }
                              else
                              {
                                  $_Value = $_PIValue.Value.ToString()
                              }
                           
                              # Output the value to the console.
                              Write-Host $_PIValue.TimeStamp.LocalDate.ToString(), "," $_Value
                          }
                          }
                          

                           

                           

                          Insert a value for a point at a given time

                           
                          function PI-InsertValue
                          {param ($PIServerName, $MyPointName, $Time, $Value)
                           
                          # Add a reference to the PI SDK assembly.
                          [reflection.assembly]::loadwithpartialname("OSIsoft.PISDK") | Out-Null
                          [reflection.assembly]::loadwithpartialname("OSIsoft.PISDKCommon") | Out-Null
                          
                          # Create a new PI SDK object.
                          $_PISDK = New-Object PISDK.PISDKClass
                          $_Asynch = New-Object PISDKCommon.PIAsynchStatusClass
                           
                          # Open a connection with the specified PI Server.
                          $_PIServer = $_PISDK.Servers.Item($PIServerName)
                           
                          # Reference the specified Point/Tag.
                          $_MyPoint = $_PIServer.PIPoints.Item($MyPointName)
                           
                          # Invoke the UpdateValue method with the given arguments.
                          Try {
                                $_MyPoint.Data.UpdateValue($Value, $Time, 1, $_Asynch)
                          }
                          Catch {
                                  Return
                          }
                           
                          # Return the Current Value.
                          Write-Host "Value inserted."
                          }
                          

                           

                           

                          Perform a tag search that returns a list of points

                           
                          function PI-TagSearch
                          {param ($PIServerName, $PointMask)
                          
                          # Verify if this function is used with a pipeline input.
                          if (@($input).count -gt 0) {$_UseWithPipeline = $true} else {$_UseWithPipeline = $false}
                          
                          # Add a reference to the PI SDK assembly.
                          [reflection.assembly]::loadwithpartialname("OSIsoft.PISDK") | Out-Null
                          [reflection.assembly]::loadwithpartialname("OSIsoft.PISDKCommon") | Out-Null
                          
                          # Create a new PI SDK object.
                          $_PISDK = New-Object PISDK.PISDKClass
                          $_Asynch = New-Object PISDKCommon.PIAsynchStatusClass
                          
                          # Create the return tag list
                          $_TagList = @()
                           
                          # Build the tag mask.
                          $_WhereClause = "Tag=" + """" + $PointMask + """"
                           
                          # Open a connection with the PI Server specified.
                          $_PIServer = $_PISDK.Servers.Item($PIServerName)
                          
                          # Retrieve all the PI Points that correspond to the tag mask.
                          $_PointList = $_PIServer.GetPoints($_WhereClause, $_Asynch)
                          
                          # Sleep for 50 ms.
                          Start-Sleep -m 50
                          
                          # Get the number of tags found.
                          $_TagCount = [int32]$_PointList.Count
                          
                          # Return the number of tags found only if not used with pipeline
                          if($_UseWithPipeline = $false)
                          {
                              Write-Host $_TagCount, "tags found for tag mask:",$_WhereClause,"."
                              Write-Host ""
                          }
                          Else
                          {
                              # Return each tag.
                              foreach ($_Point in $_PointList)
                              {
                                  if($_UseWithPipeline = $false) {Write-Host $_Point.name}
                                  $_TagList += $_Point.name
                              }
                          
                              # Return the array to be used in a pipeline.
                              return $_TagList
                          }
                          }
                          

                           You can also allow running ScriptBlocks via .NET async callbacks. Internally this is managed by converting .NET async callbacks into .NET events. This enables PowerShell 2.0 to run ScriptBlocks indirectly through Register-ObjectEvent.

                           

                           

                          Read messages from the PI Message Log

                           
                          function PI-GetMessage
                          {param ($PIServerName, $StartTime, $EndTime, $Count, $ProgramMask, $MessageMask)
                          
                          # Define an error handler.
                          trap
                          {
                              Write-Host "An error has occured."
                              continue
                          }
                          
                          # Add a reference to the PI SDK assembly.
                          [reflection.assembly]::loadwithpartialname("OSIsoft.PISDK") | Out-Null
                          [reflection.assembly]::loadwithpartialname("OSIsoft.PISDKCommon") | Out-Null
                           
                          # Create a new PI SDK object.
                          $_PISDK = New-Object PISDK.PISDKClass
                          $_Asynch = New-Object PISDKCommon.PIAsynchStatusClass
                          $_ExtendedMessageLog = New-Variable PISDK.MessageLog2
                          $_Filters = New-Object PISDKCommon.NamedValuesClass
                           
                          # Open a connection with the specified PI Server.
                          $_PIServer = $_PISDK.Servers.Item($PIServerName)
                           
                          #Get pointer to MessageLog2 Interface
                          #With a pointer to any interface on the object, you can then call
                          #QueryInterface to retrieve any secondary interface the object supports
                          $_ExtendedMessageLog = $_PIServer.MessageLog
                           
                          # Configure the filters you want to apply.
                          $_Dummy="Connection Information"
                          $_Filters.Add("Source1_Filter", [ref]$_Dummy)
                          $_EndTime = $EndTime
                          $_StartTime = $StartTime
                          if ($Count -eq $null) {$_MaxMessage = -1} else {$_MaxMessage = $Count}
                          if ($ProgramMask -eq $null) {$_ProgramMask = "*"} else {$_ProgramMask = $ProgramMask}
                          if ($MessageMask -eq $null) {$_MessageMask = "*"} else {$_MessageMask = $MessageMask}
                          $_SeverityMask = 5
                           
                          # Extract the messages.
                          # Make sure you trap possible exception,  because an exception
                          # is thrown when no messages are returned.
                          # The $_Asynch object is required but not initialized in the call.
                          #PowerShell is like C# and requires all arguments to be passed with the function.
                          $_ReturnedMessages = $_ExtendedMessageLog.List2($_StartTime, $_EndTime, `
                          $_MaxMessage, $_ProgramMask, $_MessageMask, -1, $_SeverityMask, `
                          $_Filters, $_Asynch, 0)
                          
                          # Sleep for 50 ms.
                          Start-Sleep -m 50
                           
                          # Return the number of messages found.
                          $_MessageCount = $_ReturnedMessages.Count
                          if ($_MessageCount -gt 1) {Write-Host $_ReturnedMessages.Count, "messages found."}
                          elseif ($_MessageCount -eq 1) {Write-Host $_ReturnedMessages.Count, "message found."}
                          else {Write-Host "No messages found."}
                          Write-Host ""
                          
                          # Return each message.
                          if($_MessageCount -gt 0)
                          {
                              $_MsgIndex = 0
                              foreach ($_Message in $_ReturnedMessages)
                              {
                                  $_MsgIndex += 1
                                  Write-Host $_MsgIndex, ")", $_Message.LogTime.ToString(), ";",
                                        $_Message.ID.ToString(), ";", $_Message.Source1, ";", $_Message.Message
                                  Write-Host ""     
                              }
                          }
                          

                           

                           

                          Get snapshot of a point using a pipe input

                          function PI-CurrentValuePipe
                          {param ($PIServerName)
                              process {$input | foreach {PI-CurrentValue $PIServerName $_} }
                          }
                          

                           

                          Get archive value of a point using a pipe input

                           
                          function PI-RecordedValuePipe
                          {param ($PIServerName, $Time, $Mode)
                              process {$input | foreach {PI-RecordedValue $PIServerName $_ $Time $Mode} }
                          }
                          

                           

                          1 of 1 people found this helpful
                            • Re: Powershell scripts for PI System maintenance
                              MichaelvdV@Atos

                              Wow, that's some reply, very usefull :) Most worthy of a blogpost!

                                • Re: Powershell scripts for PI System maintenance
                                  andreas

                                  Great post Mathieu - and certainly worth participating in the race for the Post-of-the-Year (vcampus.osisoft.com/.../9240.aspx)

                                    • Re: Powershell scripts for PI System maintenance

                                      Agreed, very nice post indeed Mathieu.

                                       

                                      I have started some work on powershell cmdlets for archive checking, re-processing and collective maintenance...maybe I will try to take the post of the year title away from you by posting when I am finished

                                        • Re: Powershell scripts for PI System maintenance
                                          MichaelvdV@Atos

                                          Looking forward to all the updates.

                                           

                                          @Rhys: Maybe you can make a blogpost out of it, and you can be nominated for blogpost of the year ? :)

                                            • Re: Powershell scripts for PI System maintenance
                                              MIDACO

                                              Hello All,

                                               

                                              We have developped a series of Powershell apps for PI tags creation from an interface (Cybectec SMP to PI).  The interface provide a very basic CSV file giving instruments tags and operating parameters.  We take this file, compose a tag name (according to the client's standards) and pic locations and other parameters from AF templates (!!).  We have a series of AF templates that includes the tag profile for many "intelligent devices" where we update centrally...  The Powershell creates a CSV which is fed to PI-APS.

                                               

                                              This Powershell uses PI-SDK and PI-OLEDBENT, runs automatically as a Windows 2008 tasks and send emails to administrator upon completion (ex: rejected points, completion statistics, etc.)

                                               

                                              This works very well and code updates and handling are all done by the Windows/PI administrator.  

                                               

                                              Thanks to Mathieu's PI advanced Development classroom that gave us many hints about developping with Powershell for which you can have alot of resources on the web.

                                               

                                              We're carrying on with the development of other scripts for PI performance reporting and update tag settings...  

                                               

                                              Hope that contribute to this thread...

                                               

                                              Michel

                                                • Re: Powershell scripts for PI System maintenance

                                                  Michel, it certainly does contribute to the thread, thanks for sharing.  What PI performance reporting are you looking to achieve with Powershell?

                                                    • Re: Powershell scripts for PI System maintenance
                                                      MIDACO

                                                      Hi Rhys,

                                                       

                                                      We have created a series of PerfMon tags for the PI server as well as watchdog tags for the interfaces.  The client wants a daily report giving the server stats on his email.

                                                       

                                                      We used Powershell to execute SQL statements on PI-OLEDB to get current/min/max/24hr avg for all of these tags as well as totalizers on watchdogs to compute the various interfaces and PI server uptime.  All of this is nicely set into an Excel spreadsheet attached to the email we sent to the distribution list.  We use PI-AF to set the app configuration (Ex: email distribution list).

                                                       

                                                      Powershell is very good and simple to handle text files.  For instance, there are out-of-the-box single line statement to load an object with a CSV file (ImportCSV) and output to a CSV file (ExportCSV).  Same for emailing (Send-MailMeesage)... Naturally, you have have acces to all .NET library or any other libraries like PISFK & All.

                                                       

                                                      The language is very intuitive and doesn't requires a development environment or a compiler.... Simply Notepad.exe (... I rather recommand Notepad ++ which is much better graphically and support Powershell of indentation and commands colors ).

                                                       

                                                      Powershell is the choice for any server based applications that doesn't require GUI.  For these apps, we used one third of the time he expected by the client for the programming.  Moreover, the implementation and evolution from the DEV to PROD environment is extremely efficient since it is just a matter to copy a text file (i.e. the script).  Thus, we succeeded to maintain a low TCO for this series of apps.

                                                       

                                                      Michel.

                                                       

                                                       

                                                      1 of 1 people found this helpful