|
|
|
@@ -793,27 +793,54 @@ in the codebase for the forward-compat shape, but the gateway-side
|
|
|
|
|
`AcknowledgeAlarmByName` when the public RPC supplies a recognizable
|
|
|
|
|
`Provider!Group.Tag` reference.
|
|
|
|
|
|
|
|
|
|
**Opt-in managed GUID ack.** Setting `MXGATEWAY_USE_MANAGED_ALARM_ACK=1`
|
|
|
|
|
in the gateway's environment (workers inherit it) routes GUID-keyed acks
|
|
|
|
|
through `aaAlarmManagedClient.AlarmClient.AlarmAckByGUID` instead of the
|
|
|
|
|
wnwrap method. That managed method is implemented on this build and
|
|
|
|
|
carries operator domain and full name natively. The worker reaches it by
|
|
|
|
|
reflection (`AaManagedAlarmAckConsumer`) because the members are
|
|
|
|
|
non-public, and runs its own Initialize → Register → Subscribe lifecycle
|
|
|
|
|
against the alarm subscription expression. The path is deliberately
|
|
|
|
|
conservative:
|
|
|
|
|
**Opt-in managed GUID ack — does not work on this rig (live-tested
|
|
|
|
|
2026-10-18).** Setting `MXGATEWAY_USE_MANAGED_ALARM_ACK=1` in the
|
|
|
|
|
gateway's environment (workers inherit it) makes the worker build an
|
|
|
|
|
`AaManagedAlarmAckConsumer`, which drives
|
|
|
|
|
`aaAlarmManagedClient.AlarmClient` by reflection (its members are
|
|
|
|
|
non-public) and is meant to take GUID-keyed acks in place of the
|
|
|
|
|
wnwrap method. The live test shows it cannot do that as built, so leave
|
|
|
|
|
the flag off.
|
|
|
|
|
|
|
|
|
|
- If the DLL cannot load or the lifecycle returns a non-zero status, the
|
|
|
|
|
worker drops back to the wnwrap ack path; alarm reads never fail
|
|
|
|
|
because of it.
|
|
|
|
|
- Subtag-mode acks (forced subtag, or failover currently on the standby)
|
|
|
|
|
stay on the subtag consumer: their GUIDs are synthetic and only it can
|
|
|
|
|
resolve them.
|
|
|
|
|
- By-name acks stay on wnwrap — `AlarmClient` has no by-name ack.
|
|
|
|
|
The test raised `TestMachine_001.TestAlarm001` with a secured write,
|
|
|
|
|
read its GUID from the wnwrap XML snapshot (the public API exposes no
|
|
|
|
|
alarm GUIDs), and acknowledged it through the `AcknowledgeAlarm` RPC
|
|
|
|
|
with the flag on:
|
|
|
|
|
|
|
|
|
|
A zero return still means *accepted*, not *applied*; a secured
|
|
|
|
|
(`MxSecurityOperate`) alarm needs an authenticated operator. The skip-gated
|
|
|
|
|
`AlarmManagedGuidAckLiveSmokeTests` asserts the ack actually lands.
|
|
|
|
|
| Step | Result |
|
|
|
|
|
|---|---|
|
|
|
|
|
| RPC ack by GUID, flag off (control) | `NotImplementedException`; `.Acked` stays `False` |
|
|
|
|
|
| RPC ack by GUID, flag on | Same `NotImplementedException`; `.Acked` `False`, `.AckMsg` empty |
|
|
|
|
|
| `AlarmClient.RegisterConsumer` in a process with a registered wnwrap consumer | `-65` — and wnwrap gets `-65` if the managed client registered first; a real `hWnd` does not help |
|
|
|
|
|
| Managed client alone in its own process, records loaded | `AlarmAckByGUID` → `-1`, `SelectByGUID` → `-1` for the wnwrap GUID in both byte orders, `AlarmAckSelected` → `-57` |
|
|
|
|
|
|
|
|
|
|
Three separate problems follow:
|
|
|
|
|
|
|
|
|
|
1. **The two libraries cannot share a process.** The worker always runs
|
|
|
|
|
a wnwrap reader, so the managed `RegisterConsumer` fails with `-65`.
|
|
|
|
|
The dispatcher is built to drop back to the wnwrap ack path on a
|
|
|
|
|
lifecycle failure (so alarm reads keep working), and it does so
|
|
|
|
|
silently — which is why the flag-on RPC is indistinguishable from the
|
|
|
|
|
control.
|
|
|
|
|
2. **The managed client does not recognise the wnwrap GUID.** `-1` from
|
|
|
|
|
`SelectByGUID` is "not found", not a security refusal, even with the
|
|
|
|
|
client holding records. Getting the client's own identifier for the
|
|
|
|
|
alarm is not reliable either: `GetHighPriAlarm` mostly throws the
|
|
|
|
|
FILETIME `ArgumentOutOfRangeException` described above. The
|
|
|
|
|
`MxSecurityOperate` question was therefore never reached.
|
|
|
|
|
3. **The gateway does not send the identity fields.** Its GUID arm fills
|
|
|
|
|
`OperatorNode`, `OperatorDomain` and `OperatorFullName` with empty
|
|
|
|
|
strings, so the domain and full name the managed method carries
|
|
|
|
|
would not arrive through the public RPC even if 1 and 2 were solved.
|
|
|
|
|
|
|
|
|
|
A working managed ack would need the client hosted out of process, a way
|
|
|
|
|
to resolve the alarm to the identifier the managed client uses, and the
|
|
|
|
|
identity fields plumbed through the gateway. Routing rules the worker
|
|
|
|
|
already applies stay correct and would carry over: subtag-mode acks
|
|
|
|
|
(synthetic GUIDs) stay on the subtag consumer, and by-name acks stay on
|
|
|
|
|
wnwrap because `AlarmClient` has no by-name ack. The skip-gated
|
|
|
|
|
`AlarmManagedGuidAckLiveSmokeTests` exercises the in-process
|
|
|
|
|
arrangement and hits problem 1.
|
|
|
|
|
|
|
|
|
|
### 5. STA / threading — resolved
|
|
|
|
|
|
|
|
|
|