PIServer.FindChangedPIPoints Method
- Last UpdatedJan 12, 2026
- 5 minute read
- PI System
- AF SDK 3.2.0
- Developer
Find all the PI Points that have changed in the PIServer.
Namespace: OSIsoft.AF.PI
Assembly: OSIsoft.AFSDK (in OSIsoft.AFSDK.dll) Version: 3.2.0.7
Syntax
public IList<PIPointChangeInfo> FindChangedPIPoints( int maxCount, Object cookie, out PIPointChangesCookie nextCookie, IEnumerable<PIPoint> filterPoints = null )
Public Function FindChangedPIPoints ( maxCount As Integer, cookie As Object, <OutAttribute> ByRef nextCookie As PIPointChangesCookie, Optional filterPoints As IEnumerable(Of PIPoint) = Nothing ) As IList(Of PIPointChangeInfo) Dim instance As PIServer Dim maxCount As Integer Dim cookie As Object Dim nextCookie As PIPointChangesCookie Dim filterPoints As IEnumerable(Of PIPoint) Dim returnValue As IList(Of PIPointChangeInfo) returnValue = instance.FindChangedPIPoints(maxCount, cookie, nextCookie, filterPoints)
public: IList<PIPointChangeInfo>^ FindChangedPIPoints( int maxCount, Object^ cookie, [OutAttribute] PIPointChangesCookie^% nextCookie, IEnumerable<PIPoint^>^ filterPoints = nullptr )
member FindChangedPIPoints : maxCount : int * cookie : Object * nextCookie : PIPointChangesCookie byref * ?filterPoints : IEnumerable<PIPoint> (* Defaults: let _filterPoints = defaultArg filterPoints null *) -> IList<PIPointChangeInfo>
Parameters
- maxCount
- Type: SystemInt32
The maximum number of changes to be returned. - cookie
- Type: SystemObject
Use the return from a previous call to this method to find all changes since the last call. Pass begin monitoring for changes to PI Points on the PIServer. Pass an AFTime to find all changes, since a particular time. - nextCookie
- Type: OSIsoft.AF.PIPIPointChangesCookie
An object to pass into the next call to this method to find all changes since the previous call. - filterPoints (Optional)
- Type: System.Collections.GenericIEnumerablePIPoint
A list of PIPoint objects for which the resulting changes should be filtered.
Return Value
Type: IListPIPointChangeInfoA list of PIPointChangeInfo structures which represent the PI Points that have changed in the PIServer.
Exceptions
| Exception | Condition |
|---|---|
| ArgumentException | When the cookie is not of a valid type. |
| ArgumentOutOfRangeException | When the maxCount is less than or equal to zero. |
| PIConnectionException | A connection to the PI Data Archive server cannot be made. |
Remarks
This method uses a pipe to track changes to PIPoint objects on a PIServer. If an AFTime is
passed as the cookie, then a query is used to find changes since the given time. After the query completes, a new pipe is established to
more efficiently track changes to subsequent calls via the nextCookie. The pipe is faster and more efficient than the query.
Since the pipe is faster and more efficient users should only pass in an AFTime for the cookie on the first call. If the pipe loses connection,
then a query is used to find changes that have occurred while the pipe was down. Queries will not reveal points that have been deleted;
therefore, FindChangedPIPoints cannot report deleted points while the pipe is down unless filterPoints have been passed.
If filterPoints have been provided, then their IDs will be validated after a query is used to backfill changes that
occurred while the pipe was down. Any IDs that are not valid, will be reported as removed PI Points.
Examples
// Get the PIServers collection for the current user and default PIServer. PIServer myPIServer = new PIServers().DefaultPIServer; // Cookie used to get changes since the last call PIPointChangesCookie cookie = null; // File used to persist the cookie while the process is not running. try { // Try to open the file containing the persisted cookie using (StreamReader reader = new StreamReader("cookie.dat")) { string json = reader.ReadToEnd(); cookie = JsonConvert.DeserializeObject<PIPointChangesCookie>(json); } } catch (FileNotFoundException) { /* Cookie has never been persisted */ } catch (SerializationException) { /* Cookie could not be read */ } catch (SecurityException) { /* No permission to read this file */ } catch (IOException) { /* Some other I/O Exception */ } // If the cookie is null, initialize it to start monitoring changes if (ReferenceEquals(cookie, null)) myPIServer.FindChangedPIPoints(int.MaxValue, null, out cookie); // Perform the operation 100 times... for (int loopIndex = 0; loopIndex < 100; loopIndex++) { string piPointName = $"testPoint_{loopIndex}"; // Create a new point which should cause a change PIPoint testPoint = myPIServer.CreatePIPoint(piPointName); // Edit the point's name to cause a change testPoint.Name = $"{piPointName}_Renamed"; // Delete the point which should cause a change myPIServer.DeletePIPoint(testPoint.Name); // Log changes that have occurred since the last call IList<PIPointChangeInfo> changes = myPIServer.FindChangedPIPoints( int.MaxValue, cookie, out cookie); if (!ReferenceEquals(changes, null)) { foreach (PIPointChangeInfo change in changes) { Console.WriteLine("ID: {0} Action: {1}", change.ID, change.Action); } } // Sleep for three seconds, don't peg the CPU System.Threading.Thread.Sleep(3000); } try { // Persist cookie so that the process can pick up changes where it left off using (StreamWriter writer = new StreamWriter("cookie.dat")) { JsonSerializer serializer = new JsonSerializer(); serializer.Serialize(writer, cookie); } } catch (SerializationException) { /* Cookie could not be written */ } catch (SecurityException) { /* No permission to write this file */ } catch (IOException) { /* Some other I/O Exception */ }