CSWorks: web-based industrial automation

Of CSWorks and software development

CSWorks Alarming Performance - Lab 01

clock March 16, 2010 06:13 by author Sergey Sorokin

I am always curious about my system performance. In this lab I will give CSWorks Alarming subsystem a hard time and see how it can handle it.


CSWorks 1.1.3700.0
Server: Intel Core 2 Quad Q6600 @ 2.40GHz, 3.25 GB RAM, Windows XP SP3
Client: Intel Core 2 Duo T5300 @ 1.73GHz (notebook), 2 GB RAM, Windows XP SP3
Network: Wireless 54 Mbps


1. Install SQL Server 2008 Express on your server machine.

2. Create database "CSWorks"

3. Create AlarmEvents table - see "createCommand" parameter of <dbTarget name="Standard SQLServer DbTarget".../> in CSWorks.Server.AlarmService.exe.config.

4. Configure SQL Server data source in CSWorks.Server.AlarmService.exe.config:

<dbTargets activeDbTarget="Standard SQLServer DbTarget">
  <dbTarget name="Standard SQLServer DbTarget"  ...  connectionString="Data Source=myserverbox\SQLEXPRESS; Initial Catalog=CSWorks;user id=sa;password=youknowit" ...  maxEventAge="3600" .../>

Please note we tell CSWorks Alarm Service to keep alarm event records in the database for an hour so we can accumulate some amount of load data.

5. Restart CSWorks Alarm Service. Make sure events are now written to CSWorks database (run "select * from AlarmEvents" to confirm it).

6. Configure Silverlight web services URL for Alarm Demo application, so it can run from remote machine - make sure that ServiceReferences.ClientConfig in

C:\Program Files\CSWorks\Demo\Web\ClientBin\CSWorks.Client.AlarmDemo.xap


<endpoint address="http://myserverbox/CSWorksDemo/AlarmWebService/Service.asmx" ...>

For more details,
see this post. Starting from version 1.4.3820.0, there is no need to do that, see this post for details.

7. Run Alarm Demo from a remote client and make sure it works properly.

8. Create a script that generates 3000 alarm descriptions in 10 alarm groups (
download it here),  run "cscript genalarms.js > alarms.txt", copy generated alarm groups to Alarms.xml, alarmGroups element. Here is an excerpt:

<alarmGroup id='00000000-AAAA-0000-0000-000000000000' description='Alarm group #0000'>
    <alarm id='{00000000-0000-0000-0000-000000000000}' description='Total intake tank load, id 00000000' expression='tank1 + tank2 + tank3 + tank4' saveHistory='true' ... >
        <threshold ... message='Total intake tank load too high: {0:#,##0.00}, exceeds {1:#,##0.00}, id 00000000' ... />
    <alarm id='{00000000-0000-0000-0000-000000090299}' description='Total intake tank load, id 00090299' expression='tank1 + tank2 + tank3 + tank4' saveHistory='true' ... >
        <threshold ... message='Total intake tank load too high: {0:#,##0.00}, exceeds {1:#,##0.00}, id 00090299' ... />

These generated alarms contain references to a couple of deployment variables: totalIntakeTankLoadMax and totalIntakeTankLoadMin. Add them to Alarms.xml as well:

    <deploymentState name="Normal" isActive="true">
        <deploymentVariable name="totalIntakeTankLoadMax" type="Int32" value="380"/>
        <deploymentVariable name="totalIntakeTankLoadMin" type="Int32" value="250"/>
    <deploymentState name="Startup">
        <deploymentVariable name="totalIntakeTankLoadMax" type="Int32" value="380"/>
        <deploymentVariable name="totalIntakeTankLoadMin" type="Int32" value="250"/>
    <deploymentState name="Shutdown">
        <deploymentVariable name="totalIntakeTankLoadMax" type="Int32" value="380"/>
        <deploymentVariable name="totalIntakeTankLoadMin" type="Int32" value="250"/>

Save Alarms.xml and give CSWorks Alarm Service a couple of seconds to digest the changes (this piece doesn't scale of course, so only one server CPU is involved).

9. Add newly created alarm group ids to AlarmWebService web.config file:

      <alarmPartition ...>

          <!-- Test groups -->

          <area id="{...}" name="Test groups">

               <alarmGroup alarmGroupId='00000000-AAAA-0000-0000-000000000000' description='Alarm group #0000'/>
              <alarmGroup alarmGroupId='00000009-AAAA-0000-0000-000000000000' description='Alarm group #0009'/>

10. Subscribe to newly created alarm groups in Alarm Demo application, either using "Subscribe..." menu command:

Or you can do that in application XAML:

<alarm:AlarmSummary ... AlarmGroupIds="...;00000000-AAAA-0000-0000-000000000000;..." />

11. After running Alarm Demo on your client machine for a minute you will be able to observe 12000 new alarm events and considerable spikes in network usage:

Let It Brew

Go grab a coffee and have a chat with your colleagues while CSWorks Alarm Service generates some alarm events.

Analyze This

Let's look at the alarm activity: System Monitor -> CSWorksAlarmService performance object -> Alarm Events per second:

~730 alarm events per second on average with spikes up to 9000 events per second. This correlates with our setup, remember: an alarm becoming inactive is an event too, and we have 4 thresholds per alarm. So, each spike is basically a burst of 3000*6=18000 events generated in 5 seconds. Now let's look at the CPU usage on the server box:

- not bad, the load is distributed properly. Let's make sure that all those events actually ended up in the database:

- good, those 700 000 events definitely did. Now back to the client.

With filtering turned off, the client seems to handle the spikes pretty well: Alarm Summary items are updated with 1-3 seconds delays. Things are getting worse if you apply a filter (say, show only active alarms): delay bumps up to 15 seconds. And of course, one of the processors on the client box is overloaded by filtering and data presentation activities. And it's not easy to scale them out: Silverlight dispatcher is single-threaded. Ok, there is some space for improvement on the client side.

And a word about network traffic for the inquiring minds. Fiddler tool tells all the truth and it ain't that ugly:

- each 2.3 MB per spike translates into ~130 bytes per event. Keep in mind that every event carries a unique text message. Not bad.

Back to Normal

Restore Alarms.xml - you have made a copy of the original file before inserting 3000 alarm descriptions, didn't you?  Again, let CSWorks Alarm Service digest the changes and in a couple of seconds, alarm summary is almost clear, showing only a couple of events. The storm is over.


Server load is scaled properly, stable and predictable. Network traffic is predictable too, those performance freaks out there can gain some bandwidth using HTTP compression (yes, Silverlight supports it). Database performance doesn't seem to be an issue at all. The only bottleneck in this scenario is client CPU consumption when processing bursts of 18000 events. So, the recommendation is: if your operator needs to keep an eye on 18000 events fired in five seconds (which is very unikely), buy him/her a better client box. 

Using third-party controls

clock March 15, 2010 17:47 by author Sergey Sorokin

CSWorks client framework is all about third-party UI components. As of this writing, all major Silverlight component providers have come up with their versions of the Gauge control. In this example, I will show how you can integrate Telerik and/or ComponentOne gauge controls into CSWorks Pipes and Tanks Demo application. The result will look like this:

Here are the steps to make it work.

1. Download Telerik Silverlight controls (dlls only) and ComponentOne Studio Trial Package for Silverlight.
2. Create a folder for third-party controls - C:\Program Files\CSWorks\ThirdParty.
3. Unpack downloaded Telerik archive and install ComponentOne package.
4. Copy Telerik assemblies (Telerik.Windows.Controls.Gauge.dll, Telerik.Windows.Controls.dll, Telerik.Windows.Data.dll) and ComponentOne assemblies (C1.Silverlight.dll, C1.Silverlight.Gauge.dll) to ThirdParty folder.
5. Open C:\Program Files\CSWorks\Demo\Src\PipesAndTanksDemo\PipesAndTanksDemo.Sample.csproj in Visual Studio.
6. Add all copied third party assemblies to the project reference list.
7. Open Page.xaml and add third-party namespaces to the namespace list:

<UserControl x:Class="CSWorks.Client.PipesAndTanksDemo.Page"


8. Add gauge controls to the page and bind them to LeftPumpSpeed and RightPumpSpeed data items:

<controls:TabItem Header="HMI Controls View">
        <Grid ...>
            <Border ...>

            <!-- Telerik Gauge for left pump -->
            <Border Grid.Row="1" Grid.Column="5" Grid.RowSpan="1" Grid.ColumnSpan="3" Background="White" BorderBrush="Black" BorderThickness="1" CornerRadius="5" Padding="5,0,5,0" Margin="0,10,0,-10">
                <StackPanel Orientation="Vertical">
                    <TextBlock Text="Telerik Gauge" Foreground="Black" FontSize="8" HorizontalAlignment="Center"/>
                    <tcontrol:RadGauge x:Name="radGauge" VerticalAlignment="Bottom" >
                        <tgauge:RadialGauge  >
                            <tgauge:RadialScale Min="0" Max="200" LabelRotationMode="None" FontSize="7">
                                    <tgauge:LabelProperties FontSize="4.5"/>
                                    <tgauge:RadialRange Min="0" Max="100" StartWidth="0.05" EndWidth="0.05" Background="Green"/>
                                    <tgauge:RadialRange Min="100" Max="160" StartWidth="0.05" EndWidth="0.05" Background="Orange"/>
                                    <tgauge:RadialRange Min="160" Max="200" StartWidth="0.05" EndWidth="0.05" Background="Red" />
                                    <tgauge:Needle Value="{Binding Value, Mode=OneWay, Source={StaticResource LeftPumpSpeed}}"/>
                    <TextBlock Text="rpm" Foreground="White" FontSize="7" HorizontalAlignment="Center" VerticalAlignment="Bottom"  Margin="0,-30,0,30"/>

            <!-- ComponentOne Gauge for right pump -->
            <Border Grid.Row="1" Grid.Column="9" Grid.RowSpan="1" Grid.ColumnSpan="3" Background="White" BorderBrush="Black" BorderThickness="1" CornerRadius="5" Padding="5,0,5,0" Margin="0,10,0,-10">
                <StackPanel Orientation="Vertical">
                    <TextBlock Text="C1 Gauge" Foreground="Black" FontSize="8" HorizontalAlignment="Center"/>
                    <c1gauge:C1RadialGauge  Minimum="0" Maximum="200" Value="{Binding Value, Mode=OneWay, Source={StaticResource RightPumpSpeed}}">
                        <c1gauge:C1GaugeLabel Interval="20" Foreground="Black" Format="#" FontSize="6" FontWeight="200" Location="0.85"/>
                        <c1gauge:C1GaugeRange From="0" To="100"  Fill="Green" Location="0.45"/>
                        <c1gauge:C1GaugeRange From="100" To="160"  Fill="Orange" Location="0.45"/>
                        <c1gauge:C1GaugeRange From="160" To="200"  Fill="Red" Location="0.45"/>
                        <c1gauge:C1GaugeMark Interval="20" />
                    <TextBlock Text="rpm" Foreground="Black" FontSize="7" HorizontalAlignment="Center" VerticalAlignment="Bottom"  Margin="0,-30,0,30"/>

            <TextBlock Text="All UI elements ..." .../>

9. Build the project and start Pipes and Tanks Demo from your start menu. Enjoy professional-looking controls in action.

Setup error: Failed while processing WebVirtualDirs. (-2147024894 )

clock March 10, 2010 06:02 by author Sergey Sorokin


A few customers were getting the following message when running CSWorks installation:

Failed while processing WebVirtualDirs. (-2147024894 ) (see screenshot)

Setup log file contains the following entry:

ConfigureIIsExec:  Error 0x80070002: Failed to find Web base

Why does this happen?

CSWorks installer installs demo application to IIS (Internet Information Services) website with following properties:

  • IP address: all unassigned;
  • Port: 80;
  • Header: <empty>

These are the default settings for “Default Web Site” created by IIS installer, and they usually remain unchanged unless system administrator edits them manually. CSWorks installer assumes there is a web site with those properties running on this machine, otherwise it throws the error above.

A similar issue is discussed with WiX installer developers at http://n2.nabble.com/WriteMetabaseChanges-Error-0x80070057-failed-to-create-web-application-td3190173.html, here is an excerpt:>

“Make sure the IP, Port and Header all exactly match the website on the machine. These are the 3 things we use to determine if we've found the right website or not.”

Is it possible to improve CSWorks installer so it can handle more complex scenarios? We probably can do that, but:

  • it will increase installer complexity and decrease its reliability;
  • installer will have to make some changes in demo applications’ settings on-the-fly which is a risky thing.

We may consider adding support for those complex scenarios, but this is not a top priority at the moment. We are sorry about the inconvenience caused and we appreciate your understanding in this regard.


Before installing CSWorks, make sure that “Default Web Site” is configured to run on port 80 for all unassigned IP addresses, and host header name for this configuration is empty, as shown at this screenshot (Windows XP). When done, run CSWorks installer and make sure CSWorks demo applications work properly. All demo applications are configured to run from http://localhost/CSWorksDemo, and they won’t run if you change port or header for the web site that hosts CSWorksDemo virtual folder.

CSWorks demo and your OPC data source

clock March 8, 2010 19:48 by author Sergey Sorokin

After installing CSWorks, many of you are tempted to connect it to your OPC data source. Here is a quick step-by-step guide how you can do that in five minutes.

In this example, I will assume we are dealing with Matrikon OPC Simulation Server - you can download it for free from Matrikon website. After installing Matrikon components, you can start tweaking CSWorks Pipes and Tank Demo so it uses data from Matrikon OPC Server.

Add new data source to LiveData Service configuration

Add a few lines to C:\Program Files\CSWorks\Framework\Server\CSWorks.Server.LiveDataService.exe.config:

    <opcLiveDataSources type="CSWorks.Server.DataSource.Opc.OpcLiveDataSource, CSWorks.Server.OpcProvider">
      <opcLiveDataSource name="OpcMatrikon" sampleBufferLength="16" hostName="localhost" progId="Matrikon.OPC.Simulation.1" subscriptionUpdateRate="250">
          <template name="matrikonBoolTag" type="Boolean" readPath="Random.Boolean" canWrite="true"/>


Restart LiveData Service so your changes take effect and the service connects to the data source.

Add new data source to LiveData Server topology configuration

Add one line to C:\Program Files\CSWorks\Demo\Web\LiveDataWebService\web.config:

      <liveDataPartition name="partition1" primaryLiveDataServer="liveDataServer_1_primary" secondaryLiveDataServer="">
          <dataSource name="OpcMatrikon"/>

Now LiveData Web Service knows where to get data for OpcMatrikon data source.

Modify demo application

Run Microsoft Visual Studio and open Pipes and Tanks Demo project at C:\Program Files\CSWorks\Demo\Src\PipesAndTanksDemo\PipesAndTanksDemo.Sample.csproj. Let's make several additions to the Page.xaml file.

Add a new data item that gets data from the boolean tag configured for Matrikon OPC Server:

        <d:BoolDataItem x:Key="TestValve" Id="type in new guid here" DataSource="OpcMatrikon" TemplateName="matrikonBoolTag" Parameters=""/>

Add a few visual elements to the upper left corner of the screen and bind them to the new data item:

            <controls:TabItem Header="HMI Controls View">
                    <Grid ...>
                        <pipes:RightValve Grid.Row="0" Grid.Column="3" IsOpen="{Binding Value, Mode=OneWay, Source={StaticResource TestValve}}" OpenColor="Black" ClosedColor="Black" IsEnabled="False" Margin="-16,0,16,0"/>
                        <PipesAndTanksDemo:Wireframe Grid.Row="0" Grid.Column="3" Status="{Binding Status, Mode=OneWay, Source={StaticResource TestValve}}" Margin="-16,0,16,0"/>
                        <pipes:RightTWay Grid.Row="0" Grid.Column="2" IsFilled="{Binding Value, Mode=OneWay, Source={StaticResource TestValve}}" FillColor="Coral" Margin="-16,0,16,0"/>
                        <PipesAndTanksDemo:Wireframe Grid.Row="0" Grid.Column="2" Status="{Binding Status, Mode=OneWay, Source={StaticResource TestValve}}" Margin="-16,0,16,0"/>


Now we have a valve and a t-way joint that supply some coral-colored liquid to Tank 1. Also, we have added a couple of Wireframe elements that will tell us if something is wrong with Matrikon boolean tag.

Time to tell DataManager that we have a new data item. Add a command to the Page_Loaded() handler in Page.xaml.cs:

        void Page_Loaded(object sender, RoutedEventArgs e)
          dataManager.DataItems.Add(Resources["TestValve"] as DataItem);

Do not forget to update the id of the datamanager in the Page.xaml, otherwise LiveData Service will keep using cached list of required data items and Matrikon tag value will never be returned:

        <d:DataManager x:Key="DataManager" Id="type in new guid here" />

We are done. Build client application and run it at http://localhost/CSWorksDemo/PipesAndTanksDemo.html (or click Start menu and choose All Programs -> CSWorks ->  Client Samples -> Pipes and Tanks Demo). The left upper corner of the screen will have some new visual elements - see screenshot.


Check names

Invalid configuration settings may prevent CSWorks LiveData Service from connecting to OPC servers. Make sure you have specified proper OPC data source attributes (opcLiveDataSource element in the config file):

  • hostName: must contain the name or the IP address of the computer running OPC server instance; if you specify host IP address, this will eliminate the need for the host name resolution, leaving less space for potential errors;
  • progId: must contain program id or guid of the OPC server; if you specify OPC server guid, this will eliminate the need to perform progid-to-guid mapping, leaving less space for potential errors.

Make sure you have specified correct read/write path(s) in template descriptions (see template elements in the data source definition) and template parameters (check your client application that supplies template parameters). If something is wrong, you will probably get an error from LiveData Service saying “Cannot add to OPC group”.

COM/DCOM security issues

In some cases, especially if you run OPC server on a separate computer, you may get security-related errors. Here is one of them: Data source <data source name>, cannot retrieve OPC server guid by program id <program id> on host <OPC server host name or IP address>.

When CSWorks LiveData service is trying to instantiate an OPC server, it calls .NET method Type.GetTypeFromProgID() method to get type information for this COM object. This method may fail for a number of reasons: improperly registered COM component, incorrect hostname or progId settings (see above), COM/DCOM security restrictions (see below) etc. Unfortunately, this piece of .NET/COM interop does not provide too much diagnostics info.

Another kind of message you may get is: Cannot create instance of OPC server <OPC server progid or guid> on machine <OPC server host name or IP address>, error Retrieving the COM class factory for remote component with CLSID <OPC server guid> from machine <OPC server host name or IP address> failed due to the following error: 80070005.

The error code 80070005 explicitly tells the reason for the failure: access to OPC server instance is denied. The following are the steps to troubleshoot COM/DCOM security issues.

Step one. Try connecting to the OPC server in question from the machine where LiveData Service is running using some simple OPC client software (Matrikon OPC Explorer is a good choice). If you fail to do that, investigate this issue using your usual DCOM troubleshooting routine. Here is a piece of advise though.

Checking “Launch and Activation” and “Access” permissions would probably be the first thing to check. In the case with Matrikon Simulation OPC Server, we did not have any issues with COM/DCOM security, mostly because Matrikon installer lets everyone access this OPC Server. You can verify it by running dcomcnfg tool on the OPC server machine and looking at Matrikon Simulation OPC Server configuration - it explicitly says that "Everyone" has "Launch and Activation" and "Access" permissions for this component, see screenshot. This cannot be considered safe practice, but makes casual user's life a bit easier.

Step two. After you have connected to the OPC server using OPC client software, try starting CSWorks LiveData Service again. You may keep getting the “access denied” error, regardless of the fact that OPC server may be already configured to be accessed by “Everyone”: “Everyone” may not include accounts based on remote machines. In our case, the problem is in the specific account CSWorks LiveData Service runs under – by default, it runs under “Network Service” Windows built-in account. Try running CSWorks LiveData Service under the account you were using on step one to run the OPC client, you probably did it using your personal account – local or domain-based. This should help in 99% of cases. After making sure that LiveData Service works, you will have to:

  • decide which account you want to use in the production environment (you probably don’t want to use your personal account for that);
  • give this account "Launch and Activation" and "Access" permissions for the OPC server;
  • configure CSWorks LiveData Service to run under this account.

64-bit implications

Please don’t expect 32-bit version of CSWorks LiveData Service to work with a 64-bit OPC server.

Desktop interaction issues

Some OPC servers may be implemented in a way they interact with the user: they may display some windows and/or add notification icons to the taskbar. Those OPC servers require special attention.

First, try to minimize OPC server desktop interaction. For example, Omron CX OPC Server software (that interacts with Windows desktop) has setting called “Start in Silent Mode” – turn it on.

Second, using dcomcnfg tool, make sure that the account CSWorks LiveData Service runs under (“Network Service”, “System”, or some non-built-in account) has ALL Launch and Access permissions for this OPC server component (do not trust the default settings, select "Customize" and check all permissions checkboxes for the given account explicitly).

Third, using dcomcnfg tool’s “Identity” tab, tell DCOM that "Launching" user should be used to run OPC server instance.

Remember: everytime you have issues connecting to OPC server, check CSWorks LiveData configuration settings spelling and COM/DCOM security as these two are by far the most common issues.

CSWorks Demo and LiveData Emulator OPC Server

clock March 5, 2010 22:07 by author Sergey Sorokin

When someone runs CSWorks Pipes and Tanks Demo application for the first time, the first question is: where all this data for pipes, tanks and valves comes from?

CSWorks installation package includes LiveData Emulator OPC Server component that simulates mixing process and accepts input from the user when he/she opens and closes the valves and changes mixing speed. LiveData Emulator OPC Server is useless for real-world applications but works well as a simple data source for the demo.

In order to make sure that CSWorks displays actual data supplied by this OPC data source, you may want to set up a quick demonstration and see how numbers are changing simultaneously in the demo and in your favourite OPC viewer application.

First off, if you just run OPC viewer on the demo machine and connect it to CSWorks LiveData Emulator OPC Server you will see some tags changing, but those changes won't be in sync with the demo values. This happens because of the way COM/DCOM (and OPC) works.

Unless you configured it otherwise, CSWorks LiveData Service runs under Network Service user account - a special Windows account many system services run under. When CSWorks LiveData Service is being told to access an OPC server (Emulator OPC Server in our case), it instantiates it through COM/DCOM infrastructure. By default, a COM server is started as a separate process on behalf of the launching user - Network Service. If you have a look at the process list while CSWorks demo is running you will see LiveData Emulator process running under Network Service account.

Now you run an OPC viewer application and connect it to CSWorks LiveData Emulator OPC Server. Have a quick look at the process list again - you will see that now you have another instance of LiveData Emulator process running under your personal account. So you have two emulators supplying different data to CSWorks and to the OPC viewer.

Let's make both CSWorks and OPC viewer use the same instance of the emulator. Please use Windows Service Manager to configure CSWorks LiveData Service so it runs under you personal account (say, Administrator). Also use DCOM configuration tool (dcomcnfg.exe) to make sure that LiveData OPC Emulator:

  • can be launched (Properties - Security - Launch and Activation Permissions) and accessed (Properties - Security - Access Permissions) by your personal account;
  • is instantiated runs under interactive user account (Properties - Identity).

This screenshot shows what has to be done.

After doing that, restart CSWorks LiveData Service and your OPC viewer, so they start using properly configured LiveData OPC Emulator server.
The screenshot shows three application windows: two Internet Explorer instances with CSWorks demo application, and a third-party OPC viewer that is configured to receive updates for "storage.numeric.reg01" tag. This is the item that CSWorks demo application uses to store Tank 1 fill level.

As CSWorks LiveData Emulator changes Tank 1 fill level, you see it changing in all three windows simultaneously. Perfect, we get the same data in all three windows.

After demonstrating CSWorks live data in action, do not forget to revert all changes made in DCOM configuration and service manager.

Running CSWorks demo applications from remote clients

clock February 25, 2010 00:24 by author Sergey Sorokin

One of the first things I would do after installing CSWorks is to open a browser on another machine in the network and type in "http://MyTestBox/CSWorksDemo/PipesAndTanksDemo.html", where MyTestBox is the name of the machine where I installed CSWorks.

This doesn't work. And it's not supposed to work because of the cross-domain web service call restrictions imposed by your browser. If you have a look at ServiceReferences.ClientConfig file in the Pipes and Tanks Demo xap package (CSWorks.Client.PipesAndTanksDemo.xap in your CSWorksDemo/ClientBin folder; don't worry it's just a ZIP file with XAP extension), you will find endpoint description for LiveData web service calls that looks as follows:

In our case, when Silverlight is trying to make a web service call to http://localhost/CSWorksDemo/LiveDataWebService/Service.asmx, the browser checks the URL of the application which happens to start with "http://MyTestBox". Since it doesn't start with "http://localhost", the browser considers this a potential security threat and blocks the call.

To make things work, just replace "localhost" in the config file with the name (or IP address) of your CSWorks server:

and save updated config to the xap file. Now refresh the page in the browser on the remote machine - Pipes and Tanks Demo should work fine.

Update (June 25, 2010):

with Silverlight 4, you can use relative web service addresses, see this post for details.

Installing IIS and ASP.NET

clock February 22, 2010 17:33 by author Sergey Sorokin

Users who are new to .NET web development keep asking asking questions about CSWorks installation errors related to IIS and ASP.NET, here are some of them:

Cannot connect to Internet Information Server. (-2147221164)

IIS (Internet Information Services) version 5 or higher must be installed

IIS (Internet Information Services) version 7 or higher and IIS 6 Management Compatibility (appcmd.exe) must be installed

Also, you may experience ASP.NET-related problems even after CSWorks installation: Pipes and Tanks Demo is not running and shows The remote server returned an error: NotFound (click to see troubleshooting guide).

All these messages signal about the same thing: IIS/ASP.NET is not working properly on this machine. Please follow the steps below to install IIS/ASP.NET on your machine

Windows8, Windows Server 2012, Windows 7, Windows Server 2008, Vista

I will describe the process for Windows Server 2008. Windows 7 interface is very similar, Vista interface is slightly different, but names and descriptions are pretty much the same.

In "Programs and Features", click on "Turn Windows features on or off". See screenshot.

Add Web Server Role if needed, and click on it to configure. See screenshot.

Select all Web Server role service required for ASP.NET application hosting as on the screenshot below. Please pay special attention to the "Application Development" and "Management Tools" sections. See W2K8 screenshot , or Windows 7 screenshot.

You may need to enable ASP.NET ISAPI extension manually. Find "ISAPI and CGI Restrictions" under IIS properties (see screenshot), and enable ASP.NET extensions (see screenshot).

Windows XP

Go to Settings -> Control Panel ->Add or Remove Programs -> Add/Remove Windows Components. Select "Internet Information Services", and select required components - see screenshot.

Navigate to your Microsoft .NET windows directory which is usually C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319 and run aspnet_regiis -i and aspnet_regiis -c.

Go to My Computer -> Manage -> Services and Applications -> Internet Information Services, Select "Default Web Site", right-click on it and modify ASP.NET tab of site properties so it uses ASP.NET 4.0. See screenshot.

Windows Server 2003

Go to Settings -> Control Panel ->Add or Remove Programs -> Add/Remove Windows Components. Select "Internet Information Services", and select required components - see screenshot.

Navigate to your Microsoft .NET windows directory which is usually C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319 and run aspnet_regiis -i and aspnet_regiis -c.

Go to My Computer -> Manage -> Services and Applications -> Internet Information Services, Select "Default Web Site", right-click on it and modify ASP.NET tab of site properties so it uses ASP.NET 4.0. See screenshot.


Select "Web Service Extensions" node of local IIS server and enable ASP.NET v4.0 extension.See screenshot.


Update (August 2010):

On XP or 2003, use DefaultAppPool for all CSWorks virtual directories. On Vista, 2008 and Windows 7 platforms, use "ASP.NET v4.0 Classic" for CSWorksDemo virtual directory, and "ASP.NET v4.0" for CSWorksM2MDemo virtual directory.

Update (February 2013):

Starting from version 2.5.4770.0, CSWorks uses DefaultAppPool for all virtual directories.

CSWorks 1.1.3674.0 released

clock February 18, 2010 17:23 by author Sergey Sorokin

What's new:

  • Trend Control and Trend Demo
  • Breaking change in history database format: LastValue observations
  • Multiple Historical Data improvements
  • Historical Data documentation

CSWorks 1.1.3600.0 released

clock January 11, 2010 19:33 by author Sergey Sorokin

What's new:

  • Historical Data Support

CSWorks 1.0.3580.0 released

clock October 31, 2009 22:00 by author Sergey Sorokin

What's new:

  • Documentation added
  • Improved data source error handling
  • Breaking changes in client framework: web service config files
  • Alarm Agent samples