0% found this document useful (0 votes)
7 views

TN8373 Creating ActiveX for CitectSCADA using Visual CSharp 2010

This technical paper provides a comprehensive guide on creating an ActiveX object using Visual C# 2010 for integration with CitectSCADA/Vijeo Citect. It covers the entire process from project setup, defining properties, methods, and events, to implementing a user interface and registering the COM control. The document is aimed at SCADA engineers and systems integrators with intermediate to advanced knowledge of the relevant technologies.

Uploaded by

Adailson Freitas
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views

TN8373 Creating ActiveX for CitectSCADA using Visual CSharp 2010

This technical paper provides a comprehensive guide on creating an ActiveX object using Visual C# 2010 for integration with CitectSCADA/Vijeo Citect. It covers the entire process from project setup, defining properties, methods, and events, to implementing a user interface and registering the COM control. The document is aimed at SCADA engineers and systems integrators with intermediate to advanced knowledge of the relevant technologies.

Uploaded by

Adailson Freitas
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 36

Creating ActiveX for

CitectSCADA / Vijeo Citect


using Visual C# 2010

June 2012 / Technical Paper


by Navnit Krishnan Mudaliar
Table of Contents
Abstract .................................................................................................................................................. 1
Audience ................................................................................................................................................ 1
Creating a Visual Studio Project ........................................................................................................ 2
Defining Properties and Methods .................................................................................................. 4
Defining Events................................................................................................................................. 7
User Interface (UI)............................................................................................................................ 8
Implementing the Properties and Methods ................................................................................ 11
StrProperty .................................................................................................................................. 11
IntProperty ................................................................................................................................... 11
FloatProperty............................................................................................................................... 12
SampleMethod ............................................................................................................................ 12
SampleMethodWithArgs............................................................................................................ 12
Helper Methods .......................................................................................................................... 12
Implementing the Events............................................................................................................... 13
COM Control Registration ............................................................................................................. 15
Making the Assembly COM Visible ............................................................................................. 16
Automatically Registering Assembly ........................................................................................... 17
Using the ActiveX in CitectSCADA/Vijeo Citect ............................................................................ 18
Adding the ActiveX UI to a Graphics Page ................................................................................ 18
Associating ActiveX Properties to CitectSCADA/Vijeo Citect Tags ....................................... 20
Interacting with the ActiveX via Cicode....................................................................................... 21
Calling a Method exposed by the ActiveX .............................................................................. 23
Writing and Reading a Property value exposed by the ActiveX ......................................... 24
Subscribing to Events exposed by the ActiveX ..................................................................... 25
Additional Information ........................................................................................................................ 32
Disclaimer ............................................................................................................................................ 33
Abstract
This document contains information on how to create an ActiveX object using Visual C#
2010, which can be embedded into a CitectSCADA/ Vijeo Citect Graphics page.

The document goes through creating an ActiveX object using Visual C# 2010, it shows
examples of implementing core functionality (Graphical User Interface, Properties, Methods
and Events) within the ActiveX object. And finally, step by step instructions on using each of
the implemented ActiveX functionality from within a SCADA Project.

Audience
The contents of this document are targeted towards SCADA engineers, systems integrators
and individuals with intermediate to advanced level knowledge of CitectSCADA/Vijeo Citect,
Cicode Programming and .NET Programming.

Page | 1
Creating a Visual Studio Project
Create a new Project in Visual Studio 2010 using the ‘Class Library’ template as shown
below. Give your project a name. In this example, we will name the project
‘MyFirstActiveX’.

Figure 1

Page | 2
Once the project is created, delete the automatically generated class file ‘Class1.cs’ from the
Solution Explorer.

Figure 2

Page | 3
Defining Properties and Methods

In order for the ActiveX to expose Properties and Methods, an interface needs to be defined
which will contain information related to the exposed Properties and Methods. The interface
will get registered into the system registry which then allows applications using the ActiveX
to determine the Properties and Methods exposed by the ActiveX.

To add a new Interface, use the options shown below.

Figure 3

Page | 4
Figure 4

The Interface needs to be decorated with the following attributes:

 [ComVisible(true)]
 [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
 [Guid("2E907764-32F1-4F3B-823C-11515494316E")]

The 1st attribute flags the interface to be ‘Com’ visible. This is important since CitectSCADA’s
ActiveX container is a COM client i.e. only accepts COM ActiveX.

The 2nd attribute is required by COM clients, in order to accept event notifications.

The 3rd attribute is used by the system registry when registering the Interface.

Note: the Guid must be unique. Depending on the version of Visual Studio used, you can generate a
unique Guid via the following menu option ‘Tools|Create Guid|(Guid Format 5)’. Alternatively, there
are several websites that offer generating ‘Guid’ online.

The above mentioned attributes requires reference to:


System.Runtime.InteropServices;

Page | 5
In order to expose the Properties and Methods defined in the Interface, the access modifier
for the Interface needs to be set to ‘public’

 public interface IMyFirstActiveX

Each Property/Method definition in the interface must have a unique [DispId(n)] attribute.

For this tutorial, we’ll define the following Properties and Methods:

 Properties
o Name: StrProperty DataType: string
o Name: IntProperty DataType: int
o Name: FloatProperty DataType: float
 Methods
o SampeMethod()
o SampleMethodWithArgs(string arg1)

Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace MyFirstActiveX
{
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[Guid("2E907764-32F1-4F3B-823C-11515494316E")]
public interface IMyFirstActiveX
{
#region Properties
// Define Properties exposed by the ActiveX here...

[DispId(1)]
string StrProperty { get; set; }

[DispId(2)]
int IntProperty { get; set; }

[DispId(3)]
float FloatProperty { get; set; }

#endregion

#region Methods
// Define Methods exposed by the ActiveX here...
[DispId(4)]
void SampleMethod();

[DispId(5)]
void SampleMethodWithArgs(string arg1);

#endregion

}
}

Page | 6
Defining Events

ActiveX’s can also contain Events. To expose Events to Clients so that they can subscribe to
it, we need to add an Interface similar to the Interface for Properties and Methods. This time
however the name for the interface will be ‘IMyFirstActiveXEvents’

As mentioned previously,

 The following Attributes must be set for the Interface


o [ComVisible(true)]
o [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
o [Guid("6ec6f4f9-e2c4-4705-9d3c-a521c3b32ae0")]
 The access modifier for the Interface must be set to public
 Each exposed Event must have a unique [DispId(n)] attribute specified

For this tutorial, we’ll define the following Events:

 OnValueChanged //Fires when the value of a property changes


 OnSelectionChanged //Fires when the selection changes
 OnButtonClicked //Fires when a button is clicked

Code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace MyFirstActiveX
{

[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[Guid("6ec6f4f9-e2c4-4705-9d3c-a521c3b32ae0")]
public interface IMyFirstActiveXEvents
{
[DispId(1)]
void OnValueChanged(string propertyname);

[DispId(2)]
void OnSelectionChanged(string selectedvalue);

[DispId(3)]
void OnButtonClicked();

Page | 7
User Interface (UI)

Now that we’ve decided on the Properties, Methods and Events the ActiveX will expose, let’s
create a User Interface (UI) for the ActiveX.

We’ll use the UI in this tutorial to visualise and make changes to the Properties exposed by
the ActiveX, fire the events, as well as indicate when the exposed method gets called by the
client.

Add a new Item to the project, using the ‘User Control’ template. Name it : ‘SampleUI’. As
shown

Figure 5

Page | 8
The UI will contain the following visual elements:

 Listbox
o Name: listBox1
o Items:
 Item 1
 Item 2
 Item 3
 Item 4
 Item 5
 Groupbox
o 3 x Labels
 Name: label1 Text: Str Property:
 Name: label2 Text: Int Property:
 Name: label3 Text: Float Property:
o 3 x Textbox:
 Name: txtStrProperty
 Name: txtIntProperty
 Name: txtFloatProperty
o 1 x Button
 Name: btnUpdateProperties
 Text: Update Properties
 Button
o Name: btnClickEvent
o Text: Fire OnButtonClick Event
 ListView
o Name: listView1
o Columns:
 Name: TimeStamp Text: Time Stamp
 Name: Details Text: Details

Page | 9
The final UI should look similar to this:

Figure 6

Once the UI elements are added, switch to the Code view (code behind)

The SampleUI Class will need to be decorated with the following attributes:

 [ComVisible(true)]
 [Guid("75C8832B-05CB-47D7-A6CB-0E706230BACB")]
 [ClassInterface(ClassInterfaceType.None)]
 [ComDefaultInterface(typeof(IMyFirstActiveX))]
 [ComSourceInterfaces(typeof(IMyFirstActiveXEvents))]

Next, the SampleUI class needs to implement the ‘IMyFirstActiveX’ interface. This is done by
adding the name of the interface to the class definition as shown:

public partial class SampleUI : UserControl, IMyFirstActiveX

Page | 10
Implementing the Properties and Methods

The actual implementation of the properties and methods are as follows:

Where a change in the property value will result in:

 Update of the Text displayed within the corresponding Textbox


 Firing of the ‘OnValueChanged’ event. This is done via the ‘ValueChanged()’
method.
 New line appended to the ListView stating the change in value.

As for the Methods, whenever it is called, a new line with the method name and any given
arguments will be appended to the ListView.

The ListView is updated via the ‘UpdateListView()’ method

StrProperty

private string strProperty;


public string StrProperty
{
get
{
UpdateListView("StrProperty value was requested!");
return strProperty;
}
set
{
if (strProperty != value)
{
strProperty = value;
txtStrProperty.Text = value;
ValueChanged("StrProperty");
UpdateListView("StrProperty value has been updated to: " + value);
}
}
}

IntProperty

private int intProperty;


public int IntProperty
{
get
{
UpdateListView("IntProperty value was requested!");
return intProperty;
}
set
{
if (intProperty != value)
{
intProperty = value;
txtIntProperty.Text = value.ToString();
ValueChanged("IntProperty");
UpdateListView("IntProperty value has been updated to: " + value.ToString());
}
}
}

Page | 11
FloatProperty

private float floatProperty;


public float FloatProperty
{
get
{
UpdateListView("FloatProperty value was requested!");
return floatProperty;
}
set
{
if (floatProperty != value)
{
floatProperty = value;
txtFloatProperty.Text = value.ToString();
ValueChanged("FloatProperty");
UpdateListView("FloatProperty value has been updated to: " + value.ToString());
}
}
}

SampleMethod

public void SampleMethod()


{
UpdateListView("SampleMethod() - executed!");
}

SampleMethodWithArgs

public void SampleMethodWithArgs(string arg1)


{
UpdateListView(string.Format("SampleMethod({0}) - executed!", arg1));
}

Helper Methods

private void ValueChanged(string propertyname)


{
if (this.OnValueChanged != null)
this.OnValueChanged(propertyname);
}

private void UpdateListView(string details)


{
ListViewItem item = new ListViewItem(new string[] { DateTime.Now.ToString(), details });
listView1.Items.Insert(0, item);
}

Page | 12
Implementing the Events

Events need to be implemented via a delegate. The delegate’s signature (i.e. the return type
and arguments) must match the events defined in the Interface (for this tutorial:
‘IMyFirstActiveXEvents’).

The Event names must match the ones specified in the interface as well (for this tutorial:
‘IMyFirstActiveXEvents’) .

The access modifier for both, the delegate and event must be set to ‘public’

public delegate void OnValueChangedHandler(string propertyname);


public delegate void OnButtonClickedHandler();
public delegate void OnSelectionChangedHandler(string selectedvalue);

public event OnValueChangedHandler OnValueChanged;


public event OnButtonClickedHandler OnButtonClicked;
public event OnSelectionChangedHandler OnSelectionChanged;

Now that the Events and corresponding delegates have been defined and added. We can
start using them.

We need to fire these events based on actions performed on the ActiveX’s UI. Therefore we
need to subscribe to the UI elements events. To do this, add the following lines of code to
the SampleUI constructor (after the ‘InitializeComponent();’ method):

 listBox1.SelectedIndexChanged += new EventHandler(listBox1_SelectedIndexChanged);


 btnUpdateProperties.Click += new EventHandler(btnUpdateProperties_Click);
 btnClickEvent.Click += new EventHandler(btnClickEvent_Click);

Code:

public SampleUI()
{
InitializeComponent();

listBox1.SelectedIndexChanged += new EventHandler(listBox1_SelectedIndexChanged);


btnUpdateProperties.Click += new EventHandler(btnUpdateProperties_Click);
btnClickEvent.Click += new EventHandler(btnClickEvent_Click);

Page | 13
Code:

void listBox1_SelectedIndexChanged(object sender, EventArgs e)


{
if (this.OnSelectionChanged != null)
{
string selectedValue = listBox1.SelectedItem.ToString();
this.OnSelectionChanged(selectedValue);
UpdateListView(string.Format("OnSelectionChanged({0}) event fired!", selectedValue));
}
}

void btnUpdateProperties_Click(object sender, EventArgs e)


{
this.StrProperty = txtStrProperty.Text;

int intValue;
if (int.TryParse(txtIntProperty.Text, out intValue))
this.IntProperty = intValue;

float floatValue;
if (float.TryParse(txtFloatProperty.Text, out floatValue))
this.FloatProperty = floatValue;

void btnClickEvent_Click(object sender, EventArgs e)


{
if (this.OnButtonClicked != null)
{
this.OnButtonClicked();
UpdateListView("OnButtonClicked event fired!");
}
}

Page | 14
COM Control Registration

During the registration process, certain registry keys will need to be added to allow for this
ActiveX to appear in the ActiveX controls list. This is done via the code shown below.

Note: This is a .NET assembly and therefore cannot be registered using ‘regsvr32.exe’. To
register this assembly, we need to use ‘RegAsm.exe’.

[ComRegisterFunction()]
public static void RegisterClass(string key)
{
// Strip off HKEY_CLASSES_ROOT\ from the passed key
StringBuilder sb = new StringBuilder(key);
sb.Replace(@"HKEY_CLASSES_ROOT\", "");

// Open the CLSID\{guid} key for write access


RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(), true);

// Create the 'Control' key - this allows it to show up in the ActiveX control container
RegistryKey ctrl = k.CreateSubKey("Control");
ctrl.Close();

// Create the CodeBase entry


RegistryKey inprocServer32 = k.OpenSubKey("InprocServer32", true);
inprocServer32.SetValue("CodeBase", Assembly.GetExecutingAssembly().CodeBase);
inprocServer32.Close();

// Finally close the registry key


k.Close();
}

[ComUnregisterFunction()]
public static void UnregisterClass(string key)
{
StringBuilder sb = new StringBuilder(key);
sb.Replace(@"HKEY_CLASSES_ROOT\", "");

// Open HKCR\CLSID\{guid} for write access


RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(), true);

// Delete the 'Control' key


k.DeleteSubKey("Control", false);

// Next open up InprocServer32


RegistryKey inprocServer32 = k.OpenSubKey("InprocServer32", true);

// Delete the CodeBase key


k.DeleteSubKey("CodeBase", false);

// Finally close the registry key


k.Close();
}

Page | 15
Making the Assembly COM Visible

Figure 7

Figure 8

Page | 16
Automatically Registering Assembly

We can setup visual studio to automatically register the assembly as part of the build
process. To enable this option, follow the screenshot shown below:

Figure 9

Note: To be able to register the assembly as part of the build process, you’ll need to run
Visual Studio as an ‘Administrator’.

Page | 17
Using the ActiveX in CitectSCADA/Vijeo Citect
For this tutorial, we will use the Example project which ships with CitectSCADA/Vijeo Citect
(version 7.2).

Adding the ActiveX UI to a Graphics Page

Run Citect Explorer, select the following from the Project List: ‘Example|Graphics|Pages’
using the Contents of Pages, select the ‘Test’ page (double click) as shown:

Figure 10

This should open the ‘Test’ page in Graphic Builder.

Page | 18
Once the ‘Test’ page is open, using the ‘Tools’ menu bar, select the ‘ActiveX’ button .
From the ‘Insert ActiveX Control’ popup that appears, select ‘MyFirstActiveX.SampleUI’.

Figure 11

Upon inserting the ‘ActiveX’ control on the ‘Test’ page, the properties dialog box for the
ActiveX should appear.

Figure 12

Notice the ‘Properties’ and ‘Events’ exposed by the ActiveX. These can now be associated
to Tags defined in CitectSCADA/Vijeo Citect. Save the page for now.

Page | 19
Associating ActiveX Properties to CitectSCADA/Vijeo Citect Tags

In order to associate the Properties exposed by the ActiveX to Tags defined in


CitectSCADA/Vijeo, we’ll add 3 local variables to the example project

Navigate to Citect Project Editor, then select the following options from the menu bar:
‘Tags|Local Variables’.

Using the ‘Local Variables’ form, add the following local variables:

Name Data Type


CitectFloat REAL
CitectInt INT
CitectString STRING

Having defined the ‘Local Variables’ or ‘Tags’, we can go ahead and associate the activex
properties to these tags.

Navigate back to the ‘Test’ page in ‘Graphics Builder’. Open the Properties Dialog box for
the ‘MyFirstActiveX.SampleUI’ ActiveX control, and set the association for each of the 3
Properties to the appropriate tag as shown in the table below (an example for the Float
Property is shown in
Figure 13):

ActiveX Property Name Citect/Vijeo Tag Name Update association on Event


FloatProperty CitectFloat OnValueChanged
IntProperty CitectInt OnValueChanged
StringProperty CitectString OnValueChanged

Figure 13

Page | 20
This implies that whenever the ‘OnValueChanged‘ fires, CitectSCADA/Vijeo Citect will
evaluate the ActiveX’s property value and update the associated Tag defined in
CitectSCADA/Vijeo Citect to the value of the Activex’s property.

Interacting with the ActiveX via Cicode

Cicode can be used to interact with the ActiveX. In this section of the tutorial, we’ll
demonstrate how cicode is used to perform the following:

 Call Method (Execute a Method exposed by the ActiveX)


 Set Property (Write to an ActiveX property)
 Get Property (Read from an ActiveX property)
 Event Subscription (Execute Cicode function when an ActiveX Event Fires)

Before starting with cicode, we need to take note of the following information:

 Object Name
 Event Class

Figure 14

Object Name: is used in Cicode to get a reference to the ActiveX. Once a reference is
obtained, it can be used to ‘Get’ or ‘Set’ property values as well as invoke/call methods
exposed by the ActiveX.

Event Class: is used for Event subscription. Cicode uses the ‘Event Class’ as one of the
keywords to subscribe to an Event exposed by the ActiveX.

Page | 21
Create a new Cicode file via Citect Explorer as show below:

Figure 15

Page | 22
Calling a Method exposed by the ActiveX

The ActiveX created in this tutorial exposes 2 methods (IMyFirstActiveX):

 SampleMethod()
 SampleMethodWithArgs(string arg)

To call/execute these methods, we can define functions in Cicode as shown

Code:

FUNCTION CallActiveXMethod()
OBJECT hObject = ObjectByName("AN503");
_OBJECTCallMethod(hobject, "SampleMethod");
END

FUNCTION CallActiveXMethodWithArg(STRING arg)


OBJECT hObject = ObjectByName("AN503");
_OBJECTCallMethod(hobject, "SampleMethodWithArgs", arg);
END

The ‘ObjectByName ()’ function used in our custom cicode helps us obtain a reference to the
ActiveX object. This reference is then used by ‘_OBJECTCallMethod ()’ to call/execute any of
the methods exposed by the ActiveX object.

The 2nd custom cicode function (CallActiveXMethodWithArg()), shows how the


‘_OBJECTCallMethod ()’ allows more than 2 arguments to be specified, the additional
arguments are used to specify arguments for the ActiveX method being called.

Note: For more information of the built-in cicode functions, please refer to the CitectSCADA/Vijeo
Citect Help.

Page | 23
Writing and Reading a Property value exposed by the ActiveX

Writing

There are 3 properties exposed by our ActiveX

 FloatProperty
 IntProperty
 StringProperty

The 3 properties mentioned above support ‘GET’ as well as ‘SET’. This means that we can
Read as well as Write to these properties.

To keep things simple, we can define a single cicode function which will allow us to write to
either of these properties.

Code:

FUNCTION SetActiveXProperty(STRING propertyname, STRING propertyvalue)


OBJECT hObject = ObjectByName("AN503");
_OBJECTSetProperty(hObject, propertyname, propertyvalue);
END

The ‘_OBJECTSetProperty()’allows us to update a property to a specified value. It uses


the first argument to determine the ActiveX object in context. The 2nd argument is then used
to determine the property that needs to be updated, whilst the 3rd argument specifies the
value that needs to be set. The 2nd and 3rd arguments are of ‘String’ data type.

Reading

Reading the Property value exposed by the ActiveX is very similar to writing. The main
difference being, the custom cicode function returns a value, and the built in cicode function
used to read the property value is ‘_OBJECTGetProperty()’.

Code:

STRING FUNCTION GetActiveXProperty(STRING propertyname)


STRING strValue;

OBJECT hObject = ObjectByName("AN503");


strValue = _OBJECTGetProperty(hObject, propertyname);

RETURN strValue;
END

‘_OBJECTGetProperty()’ – Returns the Value of the property as a string, which in turn is


returned by our custom cicode function ‘GetActiveXProperty()’

Page | 24
Subscribing to Events exposed by the ActiveX

The ActiveX we created exposes 3 Events.

 OnValueChanged
 OnButtonClicked
 OnSelectionChanged

OnValueChanged – this event has been subscribed to via the Tag Association (Figure 13)

As for the 2 remaining Events, we can subscribe to them via cicode as shown below.

FUNCTION Test_AN503_OnButtonClicked(OBJECT this)


Message("ActiveX Event", "OnButtonClicked event was executed!", 0);
END

FUNCTION Test_AN503_OnSelectionChanged(OBJECT this, STRING selecteditem)


Message("ActiveX Event",
"OnSelectionChanged event was executed.^r^nSelection Changed to: " +
Selecteditem,
0);
END

Note: The key element for subscribing to an ActiveX event via Cicode, is the function name
and its arguments.

Figure 16

As for the ‘FUNCTION Test_AN503_OnSelectionChanged(OBJECT this, STRING selecteditem)’ event


subscription, the function has an additional argument (‘STRING selecteditem’) which matches
the argument specified in the corresponding OnSelectionChanged event
(IMyFirstActiveXEvents).

Save the Cicode file, giving it a unique name. eg. “MyFirstActiveX.ci”

Page | 25
Navigate back to the Graphics Builder ‘Test’ page and add the following elements to the
page. This will assist in visualising values and executing the cicode defined in the previous
steps.

The top 3 elements will help visualise the Local Variable/Tag values, whilst the buttons will
help us execute the appropriate cicode function.

Figure 17

Figure 18

Page | 26
Figure 19

Figure 20

Page | 27
Figure 21

Figure 22

Page | 28
Figure 23

Figure 24

Page | 29
Figure 25

Figure 26

Page | 30
Figure 27

The ‘Test’ page should finally look similar to the one shown below:

Figure 28

Page | 31
Perform the following steps and then run the Example project to Test the ActiveX:

 Save the ‘Test’ page


 Pack (Project Editor|File|Pack)
 Compile (Project Editor|File|Compile)
 Run ‘Computer Setup Wizard’ (Citect Explorer|Tools|Computer Setup Wizard)

Additional Information
When working with ActiveX, take extreme precaution around exceptions. Any un-handled
exception thrown by the ActiveX, will result in the exception propagating to the ActiveX
container (In this case CitectSCADA/Vijeo Citect) and therefore resulting in the SCADA
system crashing.

Do not run long running blocking code on the main thread of the ActiveX, as this will result in
Citect’s main thread being blocked.

Page | 32
Disclaimer
By using the information contained within this document, you agree to the following:

Disclaimer of All Warranties

SCHNEIDER ELECTRIC (AUSTRALIA) PTY LTD DISCLAIMS ANY AND ALL


WARRANTIES WITH RESPECT TO SCHNEIDER ELECTRIC (AUSTRALIA) PTY LTD
PRODUCTS AND THE RELATED DOCUMENTATION, WHETHER EXPRESS OR
IMPLIED, INCLUDING SPECIFICALLY THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A GENERAL OR PARTICULAR PURPOSE.

CITECTSCADA/ VIJEO CITECT AND THE RELATED DOCUMENTATION ARE PROVIDED


"AS IS," AND YOUR COMPANY UNDERSTANDS THAT IT ASSUMES ALL RISKS OF
THEIR USE, QUALITY, AND PERFORMANCE.

Disclaimer of Liability

YOUR COMPANY AGREES AND ACKNOWLEDGES THAT SCHNEIDER ELECTRIC


(AUSTRALIA) PTY LTD SHALL HAVE NO LIABILITY WHATSOEVER TO YOUR
COMPANY FOR ANY PROBLEMS IN OR CAUSED BY SCHNEIDER ELECTRIC
(AUSTRALIA) PTY LTD PRODUCTS OR THE RELATED DOCUMENTATION, WHETHER
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, OR CONSEQUENTIAL (INCLUDING LOSS
OF PROFITS).

Page | 33
© 2012 Schneider Electric. All rights
reserved.

Schneider Electric (Australia) Pty Ltd


78 Waterloo Road
Macquarie Park, NSW 2113
Phone: + 61 (2) 9125 8500
Fax: + 61 (2) 9888 2941

http://www.schneider-electric.com

You might also like