InTouch AlarmViewerCtrl ApplyQuery on Indirect Tag Screens

Karen Mitchell14 min read
HMI / SCADATutorial / How-toWonderware
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Overview

Wonderware InTouch HMI projects commonly use a single template window with indirect tags to display dozens or hundreds of like assets (pumps, motors, servos, valves) without duplicating graphics. The challenge is that alarm banners are normally bound to a fixed alarm group at design time, so a single shared screen cannot dynamically show the alarm subset for whichever asset the operator has selected. This article documents two production-proven patterns for binding the AlarmViewerCtrl ActiveX control to an indirect tag window so the alarm display tracks the active asset in real time.

The first pattern uses the ApplyQuery method, which replaces the entire query of the control (provider, time range, filter, mode) when the window opens. The second pattern uses a Popup window containing the AlarmViewerCtrl and the SetQueryByName method, which retargets the control to a named alarm group passed in through a memory tag. Both patterns are supported in current AVEVA InTouch (formerly Wonderware) releases and are documented in the official AVEVA InTouch HMI documentation set.

Prerequisites

Before implementing a dynamic alarm banner on an indirect tag screen, verify the following in the development environment:

  • InTouch development license with the Alarm Viewer ActiveX option enabled. The AlarmViewerCtrl ships with the InTouch installation but is registered as an OLE control; verify it is registered on the target node with regsvr32 wwAlmVwr.ocx (path varies by version, typically under \Program Files\Wonderware\InTouch\).
  • Configured alarm groups in the Alarm DB Configurator or, in newer builds, the IDF-based alarm database. Each asset (pump1, pump2, etc.) must have its own named alarm group, and the alarm class hierarchy (Priority, Category, Area) must be assigned.
  • Local tags for each asset instance and a memory tag (e.g., indSelectedAsset) that holds the currently selected asset name and is driven by a Pick action or a Window Script.
  • Reference to AVEVA Documentation: Indirect tags and AVEVA Documentation: Use indirect tags with local tags for tag binding syntax.

How Indirect Tags Interact with the AlarmViewerCtrl

An indirect tag in InTouch is a memory tag whose dot-reference resolves to a different local or shared tag at runtime. The reference is resolved when the window is opened or when a Tagname assignment is executed. The AlarmViewerCtrl, however, does not accept indirect tag references inside its design-time configuration dialog in a useful way; the alarm group name is a string parameter to a query, not a tag. Therefore, the only practical method to retarget the control at runtime is through its programmatic method interface:

Method Purpose Typical Use
ApplyQuery Replaces the full query (provider, start, end, filter, mode) Replace the design-time $System default with a runtime-resolved provider
SetQueryByName Reapplies the query targeting a named alarm group stored in the alarm DB Popup-driven alarm display where the group name is passed through a memory tag
SetQuery Reapplies the active query without changing its parameters Force a refresh after alarm database changes
Refresh Reloads the current display from the alarm provider Refresh after ApplyQuery to force immediate re-read

Because the control exposes an OLE/COM automation interface, the methods can be invoked from a QuickScript, a Window Script, or an ActiveX event. The control's object name (default AlarmViewerCtrl1) is what the script references with a leading #.

Pattern 1: ApplyQuery on the Indirect Tag Window

This pattern places the AlarmViewerCtrl directly on the indirect tag window and runs a Window Script (typically On Show) to retarget the query based on the selected asset. It is the cleanest layout because the operator sees both the asset data and its alarms in one window, and there is no popup to dismiss.

Step 1 - Add the AlarmViewerCtrl

  1. Open the indirect tag window in WindowMaker.
  2. Insert an ActiveX control: Insert > ActiveX Control > AlarmViewerCtrl.
  3. Place it as a banner across the top or bottom of the window.
  4. Note the object name assigned to the control (e.g., AlarmViewerCtrl1). This name must be unique within the window.
  5. Set a default query of $System at design time. This default is replaced at runtime; leaving it as $System ensures the control opens successfully in WindowViewer even if the script fails.

Step 2 - Define the Asset Memory Tags

Create memory tags to hold the indirect tag targets and the alarm provider name. Typical names:

indSelectedAsset       (Memory, String, 32 chars)   // e.g. "pump1_alarms"
indAlarmProvider       (Memory, String, 64 chars)   // e.g. "\\InTouch!System"
indAlarmStart          (Memory, Integer)            // e.g. 1
indAlarmEnd            (Memory, Integer)            // e.g. 999
indAlarmFilter         (Memory, String, 16 chars)   // e.g. "All"
indAlarmMode           (Memory, String, 16 chars)   // e.g. "Summary"

Step 3 - Build the Window Script (On Show)

Attach the following QuickScript to the window's On Show event so it executes every time the operator navigates to the screen:

#AlarmViewerCtrl1.ApplyQuery(
    indAlarmProvider,
    indAlarmStart,
    indAlarmEnd,
    indAlarmFilter,
    indAlarmMode
);

Alternatively, with literal defaults used as in the original working example:

#AlarmViewerCtrl1.ApplyQuery("\\InTouch!System", 1, 999, "All", "Summary");

The double backslash in \\InTouch!System is the InTouch string escape for a single backslash required by the provider syntax \<ServerName>!<GroupName>.

Step 4 - Drive indSelectedAsset

On the parent screen that lists the assets, each asset button (or Pick action) should write the asset's alarm group name into indSelectedAsset and then call Show "indServoScreen". Example button script:

indSelectedAsset = "pump1_alarms";
indAlarmProvider = "\\InTouch!System";
indAlarmFilter   = "All";
indAlarmMode     = "Summary";
Show "indServoScreen";

Because the On Show script on the indirect screen reads these memory tags and calls ApplyQuery, the AlarmViewerCtrl refreshes against the correct alarm group automatically.

Pattern 2: Popup Window with SetQueryByName

Pattern 2 is the more conservative approach used in long-running Wonderware installations. The AlarmViewerCtrl is placed on a separate Popup window that is invoked from the indirect asset screen. The Popup contains its own Window Script that calls SetQueryByName against a memory tag holding the alarm group name. This pattern is especially useful when the same alarm popup must be reused from many different asset templates.

Step 1 - Create the Popup Window

  1. Create a new window named Popup_Alarm with the Replace attribute and the Overlap and Popup options enabled in WindowMaker.
  2. Insert the AlarmViewerCtrl and note its object name (e.g., AlarmViewerCtrl15).
  3. Set the default query to the most common alarm group or to $System as a fallback.

Step 2 - Define the Group Name Memory Tag

PopUp_AlmGrp          (Memory, String, 32 chars)   // alarm group name passed to SetQueryByName

Step 3 - Window Script on the Popup

Attach the following QuickScript to the Popup window's On Show event:

#AlarmViewerCtrl15.SetQueryByName(PopUp_AlmGrp);

This method looks up the alarm group by name within the currently configured alarm provider (the one set on the control at design time) and applies it. SetQueryByName is preferred over ApplyQuery when the alarm provider path is fixed and only the group name changes per asset.

Step 4 - Invoke the Popup from the Asset Screen

On the indirect asset screen, place a button labeled "Alarms" with the following action script:

PopUp_AlmGrp = "U27";   // the alarm group name for the currently selected asset
Show "Popup_Alarm";

The PopUp_AlmGrp assignment must occur before the Show statement so the On Show script of the popup can read the value when it executes.

Resolving OLE Error 0x100E0202 After Window Import or Export

A common production failure when the AlarmViewerCtrl is added to a screen and the window is later imported into another development machine (or even re-imported into the same application) is the following runtime message in the InTouch log viewer:

OLE Error 0x100E0202: Error processing 'indServoAlarms.ApplyQuery' on method call (add param str).
OLE object reference is not bound to an OLE object.

The hex code 0x100E0202 is a generic OLE/automation binding failure. In an InTouch context it almost always means one of the following:

Root Cause How to Verify Corrective Action
The control's object name in the imported window does not match the script's hard-coded reference (e.g., the script calls #AlarmViewerCtrl1.ApplyQuery but the import renumbered it to indServoAlarms). Right-click the ActiveX control in WindowMaker and confirm its Name property matches the # reference in the script. Rename the control to match the script (or rewrite the script to use the actual object name). Object names should be unique across the window.
The ActiveX class ID was stripped during the Export Window / Import Window round trip because the target application did not have the AlarmViewerCtrl registered. On the target node, run regedit and look under HKEY_CLASSES_ROOT\CLSID for the AlarmViewerCtrl class ID. If absent, the OCX is unregistered. Reinstall InTouch components or run regsvr32 on the .ocx file from a working installation.
The script is running before the ActiveX control has finished initializing, especially on a slow VM or RDP session. Reproduce the error only on slow startup; the same window opens cleanly on the second navigation. Wrap the method call in a small Delay or attach the script to the ActiveX control's On Loaded event rather than the window's On Show event.
The window was saved in a newer InTouch version (e.g., 2020 R2) and imported into an older version (e.g., 2014 R2) that uses a different OCX build. Check Help > About InTouch on both machines. Re-create the control on the older target, or upgrade the target runtime.
Field tip: After every Window > Export / Window > Import operation, open each window that contains an AlarmViewerCtrl and confirm that the control's object name, the script's #<Name> reference, and the Class ID in the ActiveX wrapper are all consistent. The InTouch message viewer is the fastest place to catch a 0x100E0202 failure before operator testing.

Parameter Reference for ApplyQuery

The full signature of the ApplyQuery method, in the order the automation interface expects arguments, is:

HRESULT ApplyQuery(
    [in] BSTR   bstrProvider,   // e.g. "\\InTouch!System"
    [in] long   lStart,         // relative time start, in seconds
    [in] long   lEnd,           // relative time end, in seconds
    [in] BSTR   bstrFilter,     // "All", "Active", "Unacknowledged", or a custom filter
    [in] BSTR   bstrMode        // "Summary" or "History"
);
Argument Type Allowed Values Notes
bstrProvider String \<Server>!<GroupName> or \<Server>!$System The leading \ is required. The provider is configured in the Alarm DB or in the IDF for the alarm source node.
lStart Integer 0 to 86400 (seconds back from now) For Summary mode, use small positive integers such as 1 to include only currently active alarms.
lEnd Integer 0 to 86400 For Summary mode, use a large value such as 999 to include all currently active and unacknowledged alarms.
bstrFilter String All, Active, Unacknowledged, or custom filter expression Custom filters use the Alarm DB filter syntax (e.g., Priority=High).
bstrMode String Summary or History Summary shows current state; History shows time-stamped records over the start/end range.

When passing string arguments from memory tags (Pattern 1), confirm that the memory tags are String type with sufficient length. Passing a tag of type Integer for a BSTR argument is a common cause of 0x100E0202 "add param str" failures.

Window Script Execution Order and Refresh Behavior

Understanding the order in which InTouch fires window events is essential for a stable dynamic alarm banner:

  1. On Show fires when the window is opened or revealed by Show / ShowAt. This is the most reliable place to invoke ApplyQuery or SetQueryByName because the ActiveX control is fully instantiated by the time the script runs.
  2. While Showing fires continuously while the window is visible. Use this only for low-overhead logic; calling ApplyQuery here will refire on every poll cycle and can flood the alarm provider.
  3. On Hide fires when the window is closed. Useful to clear state memory tags or detach event handlers.
  4. On Loaded on the ActiveX control itself fires once the OLE object is initialized. If On Show is firing before the control is ready (symptom: intermittent 0x100E0202 on first open), move the method call here instead.

After ApplyQuery or SetQueryByName it is generally unnecessary to call Refresh; the method itself queues a re-read. If alarms appear stale in History mode, however, add a #AlarmViewerCtrl1.Refresh(); call immediately after the query method.

Advanced Patterns

Combining Indirect Tags with Filter Expressions

When the alarm group is large (e.g., a plant-wide Area_Process group) but the operator must see only the alarms relevant to a single asset, combine an indirect tag window with a filter expression rather than a per-asset alarm group. In the On Show script:

#AlarmViewerCtrl1.ApplyQuery(
    "\\InTouch!System",
    1, 999,
    "Tagname = '" + indSelectedAsset + "'",
    "Summary"
);

This technique works only when the alarm DB exposes Tagname as a queryable column; verify the column is exposed in the alarm provider configuration.

Using a Custom User-Defined Filter Stored in the Alarm DB

For deployments with many filter combinations, define named filters in the Alarm DB Configurator (e.g., Filter_HighPriority) and reference them by name in ApplyQuery:

#AlarmViewerCtrl1.ApplyQuery("\\InTouch!System", 1, 999, "Filter_HighPriority", "Summary");

Animating the Control's Visibility

To keep the alarm banner collapsed until the operator clicks a "Show Alarms" button, animate the Visible property of the AlarmViewerCtrl with a discrete expression on indAlarmsVisible (Integer memory tag, 0 or 1). The control must remain instantiated (not destroyed) for the On Show script to retarget it; therefore use Visible = No rather than deleting the window.

Verification and Commissioning

After implementation, run the following commissioning checklist before releasing the window to operations:

  1. Open the indirect screen with no alarm group selected (default $System). The control should display all system alarms without errors.
  2. From a parent screen, select asset Pump1. Confirm that indSelectedAsset = "pump1_alarms" before the indirect screen opens.
  3. Open the indirect screen. Confirm only Pump1 alarms appear in the banner. The message viewer must be free of 0x100E0202 entries.
  4. Acknowledge a Pump1 alarm on the banner. Confirm the alarm disappears from the active list and that the event is logged in the alarm history.
  5. Navigate back to the parent screen and select Pump2. Open the indirect screen. Confirm the banner retargets to Pump2 alarms within one poll cycle (default 250 ms).
  6. Close and reopen the application. Confirm the banner still retargets correctly after a cold start, which proves the On Show script and memory tag persistence are correct.
  7. Force a fault on a Pump1 alarm source from the controller (or from a simulated I/O point) and confirm the banner updates live without requiring the operator to reopen the screen.

Troubleshooting Matrix

Symptom Likely Cause Fix
Banner shows no alarms for the selected asset Memory tag indSelectedAsset not written before Show Confirm the button script sets the memory tag on the line above the Show statement
Banner shows all alarms regardless of asset On Show script is referencing $System instead of the asset group Verify ApplyQuery receives the asset group as the provider argument
0x100E0202 after import/export Object name mismatch or unregistered OCX Realign the ActiveX control's Name property with the script reference; re-register wwAlmVwr.ocx
Banner does not refresh after a new alarm is raised Alarm provider cache not invalidated Add #AlarmViewerCtrl1.Refresh(); after ApplyQuery in On Show
Banner is empty on first open, populated on second open On Show fires before ActiveX is initialized Move the method call to the control's On Loaded event
Banner shows historical alarms, not active ones bstrMode is set to History with an explicit time range Use Summary mode and a small lStart such as 1
Banner errors only on a remote View node AlarmViewerCtrl OCX not registered on the View node Install the InTouch runtime components (which include the OCX) on every View node

FAQ

Can an InTouch alarm group be assigned through an indirect tag?

No. Alarm groups are strings, not tag references, so they cannot be bound indirectly through the design-time dialog. The only supported way to retarget an AlarmViewerCtrl to a per-asset alarm group is through its method interface: ApplyQuery for full control over provider and time range, or SetQueryByName for simple group-name swaps from a Popup window.

What does OLE Error 0x100E0202 mean in an InTouch script?

It is a generic OLE/automation binding failure raised when a script invokes a method on an ActiveX control whose object reference is not bound. In AlarmViewerCtrl scenarios it is almost always caused by an object-name mismatch after a window import/export, an unregistered OCX on the target node, or the script running before the control has finished initializing.

Should I use ApplyQuery or SetQueryByName?

Use SetQueryByName when the alarm provider is fixed and only the group name changes (typical Popup pattern). Use ApplyQuery when you also need to change the provider, the time range, the filter, or the mode from values stored in memory tags driven by an indirect tag selection.

Does the AlarmViewerCtrl update live without reopening the window?

Yes. Once a query is applied, the control subscribes to alarm state changes from the configured provider and updates the banner in real time. The On Show script only needs to run once per navigation; subsequent alarm events are pushed by the alarm provider.

Where do I find the official method signatures and alarm provider syntax?

The AVEVA InTouch HMI documentation set covers the AlarmViewerCtrl method interface, the \<Server>!<GroupName> provider syntax, and the Alarm DB filter grammar. Indirect tag reference material is published at AVEVA Documentation: Indirect tags and AVEVA Documentation: Use indirect tags with local tags.

Back to blog