23 Replies Latest reply on Apr 15, 2011 6:48 PM by Ahmad Fattahi

    C# PISDK Batch List with Start and Stop Times

    mdsterman

      Hi,

       

      I am developing my first C# application using the PISDK.  I get a PIUnitBatchList from the PI Server, but when I try to assign a RecordSet to a PIUnitBatch, I get a type error.  The RecordSet.Value gives me a string batch name; not useful for getting the start, stop time.  Would someone please paste in a few lines of code that would aquire PIUnitBatches with start and stop times?

       

      Thank You

        • Re: C# PISDK Batch List with Start and Stop Times
          Ahmad Fattahi

          Here is an example of retrieving a BatchList RecordSet and sorting them in VB for Microsoft Excel. The C# version should not be too different in principle. Hope it serves as a good example:

           
          Private Sub cmdSearch_Click()
                Dim i As Integer
                
                SearchEnd.SetToCurrent
                SearchStart.UTCSeconds = SearchEnd - 604800#
                Set BatchList = Unit.PIUnitBatchSearch(SearchStart, SearchEnd)
                Set rsBatches = BatchList.Recordset
          '      rsBatches.Sort = "UnitName ASC, BatchID ASC, StartTime ASC"
          '      rsBatches.Sort = "BatchID DESC, StartTime ASC"
          '      rsBatches.Sort = "BatchID ASC"
                rsBatches.Sort = "UnitName ASC, BatchID DESC, StartTime ASC"
                rsBatches.MoveFirst
                i = 2
                Do While Not rsBatches.EOF
                      Cells(i, 1).Value = rsBatches.Fields.Item(1).Value
                      Cells(i, 2).Value = rsBatches.Fields.Item(2).Value
                      Cells(i, 3).Value = rsBatches.Fields.Item(3).Value
                      Cells(i, 4).Value = rsBatches.Fields.Item(4).Value
                      Cells(i, 5).Value = rsBatches.Fields.Item(5).Value
                      Cells(i, 6).Value = rsBatches.Fields.Item(6).Value
                      Cells(i, 7).Value = rsBatches.Fields.Item(7).Value
                      Cells(i, 8).Value = rsBatches.Fields.Item(8).Value
                      Cells(i, 9).Value = rsBatches.Fields.Item(9).Value
                      Cells(i, 10).Value = rsBatches.Fields.Item(10).Value
                      rsBatches.MoveNext
                      i = i + 1
                Loop
          
          End Sub
          

           

            • Re: C# PISDK Batch List with Start and Stop Times
              andreas

              From your request i can't see the need for the recordset - so I decided to stick to the simple objects and to keep it even more simple i decided for a command line app:

               
              using System;
              using System.Collections.Generic;
              using System.Linq;
              using System.Text;
              
              namespace vCampus_1864_9624
              {
                  class Program
                  {
                      static void Main(string[] args)
                      {
                          PISDK.PISDK myPISDK = new PISDK.PISDK();
                          PISDK.Server myPIServer = myPISDK.Servers.DefaultServer;
              
                          PISDK.PIModuleDB myPIMDB = myPIServer.PIModuleDB;
                          PISDK.PIUnitBatchList myPIUnitBL = myPIMDB.PIUnitBatchSearch("*-1d","*");
              
                          foreach (PISDK.PIUnitBatch myPIUnitBatch in myPIUnitBL)
                          {
                              Console.WriteLine(myPIUnitBatch.StartTime.LocalDate.ToString() + ", " + 
                                                myPIUnitBatch.EndTime.LocalDate.ToString() + ", " + 
                                                myPIUnitBatch.BatchID.ToString()  + ", " + 
                                                myPIUnitBatch.PIUnit.Name);
                          }
                          Console.ReadKey();
                      }
                  }
              }
              

               

               

              does that help?

                • Re: C# PISDK Batch List with Start and Stop Times
                  mdsterman

                  Thank You for posting this code.  This code is essentialy the same as what I was trying, and it did not run for me either.  That led me to find the underlying cause.  I had used the COM pisdk type library for the project reference rather than the pisdk.dll.  I could not find the dll the first time I looked, and then resorted to the COM type library.  Interesting how that sort of works, but not quite.  Is the COM object for VB or something?

                    • Re: C# PISDK Batch List with Start and Stop Times
                      andreas

                      COM is for VBA, and essentially prior .NET (VB6, etc), any .NET needs the .NET assemblies as reference: OSIsoft.PISDK.dll, OSIsoft.PISDKCommon.dll, etc.

                      • Re: C# PISDK Batch List with Start and Stop Times
                        mdsterman

                        One other puzzling thing.  The foreach loop always ends with a null reference exception.  Isn't the foreach iterator supposed to prevent that?

                          • Re: C# PISDK Batch List with Start and Stop Times
                            mdsterman

                            Oh, it is probably that the most recent batch does not have an end time.

                              • Re: C# PISDK Batch List with Start and Stop Times
                                mdsterman

                                Is there a way to test for null end time without doing try catch?

                                  • Re: C# PISDK Batch List with Start and Stop Times
                                    andreas

                                    how about:

                                     
                                                foreach (PISDK.PIUnitBatch myPIUnitBatch in myPIUnitBL)
                                                {
                                                    if (myPIUnitBatch.EndTime == null)
                                                    {
                                                        Console.WriteLine(myPIUnitBatch.StartTime.LocalDate.ToString() + ", " +
                                                                         "running" + ", " +
                                                                         myPIUnitBatch.BatchID.ToString() + ", " +
                                                                         myPIUnitBatch.PIUnit.Name);
                                                    }
                                                    else
                                                    {
                                                        Console.WriteLine(myPIUnitBatch.StartTime.LocalDate.ToString() + ", " +
                                                                      myPIUnitBatch.EndTime.LocalDate.ToString() + ", " +
                                                                      myPIUnitBatch.BatchID.ToString() + ", " +
                                                                      myPIUnitBatch.PIUnit.Name);
                                                    }
                                                    
                                                }
                                    

                                    Works on my site (I must admit that I had no running batch so I did not think of handling this initially ).

                                      • Re: C# PISDK Batch List with Start and Stop Times
                                        mdsterman

                                        Hi Andreas,

                                         

                                        The null tests do not work for me.  Same as testing and array of size X for null at X + 1.  It throws an exception.  I am using try catch to handle the running batch case (ours are 2 weeks long) and that works OK.  

                                         

                                        Marty

                                          • Re: C# PISDK Batch List with Start and Stop Times
                                            andreas

                                            Martin,

                                             

                                            that might be a version issue - mine is working on VS2010 - however, the try and catch should be fine. we had a try and catch discussion here vcampus.osisoft.com/.../1142.aspx - so doing the try and catch isn't bad :-)

                                              • Re: C# PISDK Batch List with Start and Stop Times

                                                @Marty: what is the exception you get when you do your null tests? As Andreas pointed out, it may be a versioning issue... what version of .NET and the PI SDK are you using?

                                                  • Re: C# PISDK Batch List with Start and Stop Times
                                                    mdsterman

                                                    I am using VS2010, .NET Framework 4.0.  No sure how to tell the PI SDK version, but the pisdk.dll is dated 12/3/2008.  When the batch has no end time, the !=null test will throw the exception:

                                                     

                                                    "Object reference not set to an instance of an object."

                                                     

                                                    If I remove the LocalDate (as Andreas code)  I get:

                                                     

                                                    System.ArgumentNullException: String reference not set to an instance of a String.

                                                     

                                                    Parameter name: s

                                                     

                                                      at System.DateTimeParse.Parse(String s, DateTimeFormatInfo dtfi, DateTimeStyles styles)

                                                     

                                                      at System.DateTime.Parse(String s)

                                                     

                                                    Here is a code snippet:

                                                     
                                                    try
                                                    
                                                        {
                                                    
                                                            if (myPIUnitBatch.EndTime.LocalDate != null)
                                                    
                                                                timeArray[ENDTIMEINDEX] = myPIUnitBatch.EndTime.LocalDate.ToString();
                                                    
                                                        }
                                                    
                                                    catch (Exception e)
                                                    
                                                        {
                                                    
                                                            Console.WriteLine(e.Message);
                                                    
                                                            PITimeServer.PITime endTime = new PITimeServer.PITime();
                                                    
                                                            endTime.SetToCurrent();
                                                    
                                                            timeArray[ENDTIMEINDEX] = endTime.LocalDate.ToString();
                                                    
                                                        }
                                                    

                                                     

                                                      • Re: C# PISDK Batch List with Start and Stop Times
                                                        andreas

                                                        You can tell the PISDK version by Start>Programs>PI System>About PI-SDK, it shows the version in the dialog box at the bottom.

                                                          • Re: C# PISDK Batch List with Start and Stop Times

                                                            If myPIUnitBatch.EndTime object itself is null, then trying to get its .LocalDate property will definitely throw an exception - start by validating the PITime object itself before to access any of its properties.

                                                             

                                                            Hope this helps!

                                                              • Re: C# PISDK Batch List with Start and Stop Times
                                                                mdsterman

                                                                My PI-SDK version is 1.3.6.

                                                                 

                                                                To Steve's point:  This is a case with a valid start time, but no end time (batch is still running).  The question is, can I test for null endtime without throwing an exception?  

                                                                  • Re: C# PISDK Batch List with Start and Stop Times
                                                                    ken

                                                                    I wrote a short C# program to show how to do it.

                                                                     

                                                                    The key is what Steve said: Check the validity of the EndTime object before trying to call any of its methods.

                                                                     

                                                                    That will avoid an exception.

                                                                     

                                                                    -----------------

                                                                     

                                                                    I created a C# program with a windows form containing three buttons:

                                                                     

                                                                    button1: creates a batch

                                                                     

                                                                    button2: sets the end time of the batch

                                                                     

                                                                    button3: checks the end time of the batch.

                                                                     

                                                                    -----------------

                                                                     

                                                                    Here is the source code:

                                                                     
                                                                    using System;
                                                                    using System.Collections.Generic;
                                                                    using System.ComponentModel;
                                                                    using System.Data;
                                                                    using System.Drawing;
                                                                    using System.Linq;
                                                                    using System.Text;
                                                                    using System.Windows.Forms;
                                                                    
                                                                    namespace CSharpBatchNullEndTime
                                                                    {
                                                                       public partial class Form1 : Form
                                                                       {
                                                                          PISDK.PISDKClass g_SDK;
                                                                          PISDK.Server g_PIServer;
                                                                          PISDK.PIBatch g_Batch;
                                                                          
                                                                          public Form1()
                                                                          {
                                                                             InitializeComponent();
                                                                          }
                                                                    
                                                                          private void Form1_Load(object sender, EventArgs e)
                                                                          {
                                                                             g_SDK = new PISDK.PISDKClass();
                                                                             g_PIServer = g_SDK.Servers.DefaultServer;
                                                                             g_PIServer.Open("");
                                                                          }
                                                                    
                                                                          private void button1_Click(object sender, EventArgs e)
                                                                          {
                                                                             PISDK.PIBatchDB myBDB;
                                                                             PITimeServer.PITime startTime;
                                                                    //
                                                                    // Create batch
                                                                    //
                                                                             myBDB = g_PIServer.PIBatchDB;
                                                                             startTime = new PITimeServer.PITimeClass();
                                                                             startTime.SetToCurrent();
                                                                             g_Batch = myBDB.Add("TestBatch",null,null,startTime,null);
                                                                          }
                                                                    
                                                                    
                                                                          private void button2_Click(object sender, EventArgs e)
                                                                          {
                                                                             PITimeServer.PITime endTime;
                                                                             if (null == g_Batch) {
                                                                                MessageBox.Show("No Batch");
                                                                             }else{ 
                                                                                endTime = new PITimeServer.PITimeClass();     // Set end time of batch if it exists
                                                                                endTime.SetToCurrent();
                                                                                g_Batch.SetEndTime(endTime);
                                                                             }
                                                                          }
                                                                    
                                                                          private void button3_Click(object sender, EventArgs e)
                                                                          {
                                                                             if (null == g_Batch) {
                                                                                MessageBox.Show("No Batch");
                                                                             }else{
                                                                                if (null == g_Batch.EndTime)     // check the end time of the batch if it exists
                                                                                {
                                                                                   MessageBox.Show("No end time");
                                                                                }else{
                                                                                   MessageBox.Show("Batch end Time = " + g_Batch.EndTime.LocalDate.ToString());
                                                                                }
                                                                             }
                                                                          }
                                                                       }
                                                                    }
                                                                    

                                                                     

                                                                      • Re: C# PISDK Batch List with Start and Stop Times
                                                                        mdsterman

                                                                        This might work because the optional endTime argument is set to null.  (not sure, I am not good with Forms projects).

                                                                         
                                                                        g_Batch = myBDB.Add("TestBatch", null, null, startTime, null);
                                                                        

                                                                         

                                                                         

                                                                        I am working with pre-existing batches where, perhaps, the endtime is not specified.  Any sort of null == g_Batch.EndTime test will throw and exception

                                                                          • Re: C# PISDK Batch List with Start and Stop Times
                                                                            mdsterman

                                                                            Another observation:

                                                                             

                                                                            Statments like g_SDK = new PISDK.PISDKClass(); do not compile for me.  I always need to change them to g_SDK = new PISDK.PISDK;  The errors are:error CS1752: Interop type 'PISDK.PISDKClass' cannot be embedded. Use the applicable interface instead.

                                                                             

                                                                            The type 'PISDK.PISDKClass' has no constructors defined

                                                                             

                                                                            Thoughts on that?

                                                                              • Re: C# PISDK Batch List with Start and Stop Times
                                                                                ken

                                                                                "Statments like g_SDK = new PISDK.PISDKClass(); do not compile for me"

                                                                                 

                                                                                I'm using Visual Studio 2008 and a standalone C# windows form program. If your environment works differently that is okay. It shouldn't make any difference as long as you get a valid object.

                                                                                 

                                                                                Here is the same program written as a console app which doesn't use PISDKClass().

                                                                                 

                                                                                ---------------------------

                                                                                 
                                                                                using System;
                                                                                using System.Collections.Generic;
                                                                                using System.Linq;
                                                                                using System.Text;
                                                                                
                                                                                namespace CSharpBatchNullEndTimeConsole
                                                                                {
                                                                                   class Program
                                                                                   {
                                                                                      static void Main(string[] args)
                                                                                      {
                                                                                         PISDK.PISDK g_SDK;
                                                                                         PISDK.Server g_PIServer;
                                                                                         PISDK.PIBatch g_Batch;
                                                                                         PISDK.PIBatchDB myBDB;
                                                                                         PITimeServer.PITime startTime;
                                                                                         PITimeServer.PITime endTime;
                                                                                //
                                                                                // Create SDK object and open default server
                                                                                //
                                                                                         g_SDK = new PISDK.PISDK();
                                                                                         g_PIServer = g_SDK.Servers.DefaultServer;
                                                                                         g_PIServer.Open("");
                                                                                //
                                                                                // Add batch with no end time
                                                                                //
                                                                                         myBDB = g_PIServer.PIBatchDB;
                                                                                         startTime = new PITimeServer.PITime();
                                                                                         startTime.SetToCurrent();
                                                                                         g_Batch = myBDB.Add("TestBatch", null, null, startTime, null);
                                                                                //
                                                                                // Check for null end time for batch
                                                                                //
                                                                                         if (null == g_Batch.EndTime) {
                                                                                            Console.Out.WriteLine("No End Time");
                                                                                         }else{
                                                                                            Console.Out.WriteLine("Batch End Time = " + g_Batch.EndTime.LocalDate.ToString());
                                                                                         }
                                                                                //
                                                                                // Set the end time of the batch and check it again
                                                                                //
                                                                                         endTime = new PITimeServer.PITime();
                                                                                         endTime.SetToCurrent();
                                                                                         g_Batch.SetEndTime(endTime);
                                                                                         if (null == g_Batch.EndTime) {
                                                                                            Console.Out.WriteLine("No End Time");
                                                                                         }else{
                                                                                            Console.Out.WriteLine("Batch End Time = " + g_Batch.EndTime.LocalDate.ToString());
                                                                                         }
                                                                                      }
                                                                                   }
                                                                                }
                                                                                

                                                                                 

                                                                              • Re: C# PISDK Batch List with Start and Stop Times
                                                                                ken

                                                                                When the batches are created without an end time by another program (i.e. pre-existing batches), the program must set it to null, so it should be no different than my program. I'm just doing it all in one program.

                                                                                 

                                                                                If you are getting an exception on

                                                                                 

                                                                                     null == batch.EndTime

                                                                                 

                                                                                then perhaps "batch" isn't an object (i.e. it is null) in your program. You can check that first like I did.