M
Matthew Diakonov
9 min read

Legacy desktop automation for SAP and Oracle, without the RPA tax

Direct answer (verified 2026-05-19)

SAP GUI for Windows publishes its full control tree through Microsoft UI Automation. Oracle Forms reaches the same UIA tree through the Java Access Bridge. That means a UIA-based framework drives both with one selector API. You do not need SAP GUI Scripting enabled on the server, you do not need an Oracle Forms-specific connector, you do not need a per-bot license from an RPA vendor. locator("role:Edit && nativeid:tbar[0]/okcd").typeText("XD03") reaches the SAP transaction code box the same way locator("role:Edit").typeText("hello") reaches Notepad.

Every guide on this topic walks the same path. Pick an enterprise RPA platform. Buy the SAP connector. Toggle sapgui/user_scripting=TRUE on the server, beg the security review board for it, configure Local scripting in SAP Logon, install the Java Access Bridge, install the vendor designer, train three business users. Then ship a workflow that lives inside a proprietary XAML or blocky designer file, scheduled by the vendor's orchestrator, billed per bot per month. This page is about the other path. The one where SAP GUI and Oracle Forms are treated as ordinary accessible Windows apps, driven by a developer framework from your own code.

The thing every legacy-RPA guide skips

SAP GUI for Windows is a thick Win32 client. Its windows participate in the standard Microsoft UI Automation tree the same way any other Win32 process does. You can verify that in sixty seconds: open SAP Logon, run inspect.exe from the Windows SDK, hover the transaction code box. You will see the control reported as an Edit with AutomationId tbar[0]/okcd. The customer master screen reports a Pane at wnd[0]/usr. The labels report as Text elements with their German or English screen names. Every one of those is a normal UIA selector.

Oracle Forms is the awkward sibling because it is Java. Java applications publish a Swing/AWT accessibility tree, not a native Win32 one, so UIA does not see Forms controls out of the box. The standard fix is the Java Access Bridge (JAB), an Oracle/Microsoft component that bridges the Java accessibility tree into MSAA, which UIA reads. One command (jabswitch -enable), one JVM restart, and Forms controls show up as role:Text,role:Button, role:ListItem in the same UIA tree. After that, the surface is identical to driving any other Win32 app.

None of this is a hidden secret. It is just not the angle most articles take, because most articles are downstream of vendor marketing. The vendors who sell SAP connectors do not want to lead with "there is a free Microsoft API that handles this".

One locator, three legacy apps

The whole pitch is that the call shape does not change when the target app changes. The selector resolves through the same parser, the same UIA walker, the same action API.

One Terminator call. UIA does the rest. SAP, Oracle Forms, Notepad, identical path.

Your code / AI agentTerminator SDKselector.rs + uiautomation crateWindows UIA tree (SAP / Forms / Win32)desktop.locator("role:Text && name:Customer")selector.rs parses the string into a Selector ASTuiautomation crate walks the UIA tree from the desktop rootSAP GUI / Oracle Forms / Notepad each expose the same UIA interfaceIUIAutomationElement pointer with cached propsUIElement wrapper, ready for .typeText() or .click()Locator handle (same shape for every Windows app)

SAP is not a plugin. It is the canonical example in the codebase.

If you are wondering whether SAP is an afterthought, it is not. SAP appears in three places inside the Terminator monorepo, all of them committed code, none of them marketing copy. First, the workflow API uses SAP as the canonical example in its JSDoc. Open packages/workflow/src/workflow.ts at line 598 and you will find createWorkflow({name: 'SAP Login'})as the doc example for the direct pattern. Second, the structured error API uses SAP as the canonical example for the business category: packages/workflow/src/types.ts at line 219 documents WorkflowError({ code: 'SAP_DUPLICATE_INVOICE', message: 'Invoice already exists in SAP', recoverable: true }). Third, the success-summary example at types.ts:549 uses # SAP Journal Entry - Success as its Markdown summary template. The framework is shaped around the kind of workflow that ends with "invoice posted" or "journal entry created".

There is also a real integration test in the Rust core: test_sap_login_scenario at crates/terminator/tests/debugger_detach_test.rs:191. The test simulates the "Login to SAP" step of a real user's workflow and reproduces the debugger-detach error they hit during it. The test exists because someone tried to automate SAP through Terminator, ran into a CDP edge case, and we wrote a regression test against the exact scenario. That is what canonical-example looks like in practice.

3 SAP refs in code

SAP Logon is just another Win32 process to UIA. The hard work was making one selector grammar honest across SAP GUI, Oracle Forms, and every other app in the same tree.

terminator-rs

What the Windows session actually looks like

Below is an actual MCP session shape against an SAP Logon window. The assistant calls get_window_tree, gets back the UIA tree, picks the transaction code box by its AutomationId, typesXD03, and presses Enter. Same primitives as Playwright on a web page. None of it goes through SAP GUI Scripting; thesapgui/user_scripting profile parameter can be off the entire time.

MCP session against SAP Logon

SAP GUI Scripting versus UIA: the honest comparison

SAP GUI Scripting is fine when it is available. It exposes a tidy object model (session.findById) and it is what most RPA platforms wrap. The reason teams end up looking for an alternative is that the scripting flag is server-side, security teams gate it carefully, and the COM surface is hard to drive from a modern test runner. UIA bypasses that whole conversation.

Two ways to reach the same SAP transaction code box

Requires the SAP server profile to set sapgui/user_scripting=TRUE and the client SAP Logon to allow scripting. COM-based, single-threaded, fragile against version upgrades, and disabled by default in many enterprises for security review reasons.

  • Needs sapgui/user_scripting=TRUE on the server
  • Needs Local scripting allowed in SAP Logon options
  • COM/VBScript surface, hard to test in CI
  • Often blocked at security policy review

None of this means SAP GUI Scripting is wrong. If your environment already has it on and your team owns the .NET tooling, it is the faster path. The argument here is that you should not have to choose between "buy a vendor RPA platform" and "write VBScript against COM". There is a third option: a developer framework over the accessibility tree both legacy apps already publish.

What the same approach actually covers

Anything that publishes to the UIA tree is in scope. Anything that does not, is not. That is the honest line, and it is the line I would want a reader to walk away with rather than a feature matrix.

Reachable through the same selector grammar

  • SAP GUI for Windows transactions exposed as a UIA Pane tree
  • Oracle Forms via the Java Access Bridge (jabswitch -enable)
  • Win32 line-of-business apps from the 90s and 2000s
  • WPF and WinForms internal apps with no public API
  • MFC dialogs that other frameworks miss because they predate WinAppDriver
  • Mainframe terminal emulators (3270, 5250) when the emulator surfaces controls to UIA
  • Citrix and RDP, only when Terminator runs on the host session, not the thin client
  • Apps that expose nothing through accessibility (then OCR fallback, last resort)

Where this falls apart

Three places. First, when SAP GUI or Oracle Forms reaches your laptop as a video stream from a Citrix or RDP session, there is no UIA tree on your side. The framework has to run on the session host inside the published environment, not on the thin client.

Second, when an internal LOB app draws every control onto a single HWND with GDI calls instead of using a real control framework. UIA sees one giant Pane with no children. This is rare for SAP and Oracle but common for very old Delphi or custom MFC apps. Pixel and OCR are the only options there, and Terminator has them via the Windows OCR engine in crates/terminator/src/platforms/windows/engine.rs around line 763 (TryCreateFromUserProfileLanguages), but they are the fallback, not the plan.

Third, when you need an attended-bot orchestrator with a hosted job queue, formal SLA contracts, and a marketplace of pre-built activities. Terminator is a framework, not a platform. You bring the runner. If that is a non-negotiable for your org, UiPath or Power Automate is the right purchase, and using Terminator inside them as a custom activity is the better integration than rebuilding their entire control plane.

The smallest first step

On a Windows box where SAP Logon or your Oracle Forms client already runs, install the MCP agent and ask your assistant to walk the tree:

# 1. install the MCP server
claude mcp add terminator "npx -y terminator-mcp-agent@latest"

# 2. open SAP Logon (or Forms), then ask the assistant:
#    "call get_window_tree on the SAP window and find the transaction
#     code box"

# 3. read the tree it returns. role, name, AutomationId on every node.
#    that's the surface you write selectors against. nothing else to set up.

If the tree comes back with usable names and AutomationIds on the controls you care about, you have everything you need. The rest is locator() calls in a file you own.

Bring one SAP or Oracle Forms transaction. We'll drive it live on the call.

Send the screen name (or transaction code) before the call. We open SAP Logon or your Forms client, dump the UIA tree, and write the selector together. You leave with a workflow.ts file that runs against the real app, no SAP scripting flag required.

Frequently asked

Frequently asked questions

Do I need SAP GUI Scripting to automate SAP GUI from Terminator?

No. SAP GUI Scripting is the COM-based API that exposes session/Window/Connection objects to VBScript or .NET. It is one route, and the route that every legacy RPA platform wraps. The other route is Microsoft UI Automation: the same SAP GUI process publishes a UIA tree where transaction codes, text fields, table cells, and toolbar buttons appear with role, name, AutomationId, and class. Terminator drives that tree with the same selector engine it uses for Notepad. If your IT team has SAP GUI Scripting disabled at the security policy level (a common case), the UIA route still works because UIA does not depend on the SAP Scripting interface being enabled.

How does that work for Oracle Forms, which is a Java application?

Oracle Forms (Forms Builder, Forms Services) renders through a Java applet or Java Web Start runtime. Java does not expose UIA directly. The bridge is the Java Access Bridge, an Oracle/Microsoft component that exposes the Swing/AWT accessibility tree to MSAA, and that MSAA tree is read by UIA on Windows. You enable JAB once (jabswitch -enable, then restart the JVM), and from that point on, Forms controls show up in the UIA tree with role:Text, role:Button, role:ListItem, etc. The same locator() call works.

Where in the Terminator codebase is the SAP-specific stuff?

There is no SAP-specific stuff, and that is the point. The closest things are: (1) crates/terminator/tests/debugger_detach_test.rs:191 contains test_sap_login_scenario, an integration test that exercises a login workflow against a stand-in form to reproduce a real error a user hit while doing SAP login. (2) packages/workflow/src/workflow.ts:598 uses createWorkflow({ name: 'SAP Login', ... }) as the canonical example in the JSDoc. (3) packages/workflow/src/types.ts:219 documents WorkflowError({ code: 'SAP_DUPLICATE_INVOICE' }) as the example for the business-error category, and types.ts:549 uses 'SAP Journal Entry - Success' as the example onSuccess summary. SAP is treated as a normal target, not a plugin.

How do I tell whether a control in an SAP transaction is reachable via UIA?

Open the transaction. Launch Accessibility Insights for Windows (Microsoft, free) or inspect.exe (Windows SDK). Hover the control. Read off Name, ControlType (role), AutomationId, and ClassName. Those are exactly what you put after the colons in a Terminator selector. SAP GUI controls usually report ControlType as Pane, Text, Button, ComboBox, or DataItem, and the Name is the SAP screen label. If a field has no AutomationId, you anchor it with rightof:role:Text|name:Customer or has:role:Text|name:Customer. The model is the same as Playwright's locator chaining.

What about Citrix or RDP? A lot of legacy SAP and Oracle is published that way.

If the SAP GUI or Oracle Forms client runs inside a published session (Citrix, AVD, RDS), the host machine is what UIA sees. You install Terminator on the same machine where the legacy app is running, not on the thin client. For most enterprise deployments that means a Windows session host, sometimes containerised. Inside that session, UIA works the way it works on a normal Windows desktop. The only case where this falls apart is when the published app reaches your laptop as a video stream and a keyboard channel; there is no UIA tree to walk through a screen. That is the case where pixel/OCR is your only option, and where every framework, including this one, is forced into the same OCR-fallback path. Terminator's OCR engine is in crates/terminator/src/platforms/windows/engine.rs around the TryCreateFromUserProfileLanguages call at line 763, but it is the last resort, not the first.

How is this different from Power Automate Desktop's SAP automation playbook?

Power Automate Desktop wraps SAP GUI Scripting behind its own designer (the SAP modules in Power Automate Desktop assume scripting is enabled in the SAP server profile sapgui/user_scripting and on the client). The authoring surface is drag-and-drop; the unit of distribution is a flow you publish to Microsoft's cloud orchestrator. Terminator is the opposite surface: a Rust crate with TypeScript and Python bindings, no designer, no cloud control plane. You write workflow.ts files, your AI coding assistant edits them through the MCP server, and the unit of distribution is whatever your team already ships (a container, a Windows service, a CI runner). The runtime sits on UIA, so it does not depend on sapgui/user_scripting being on.

Can I record an SAP transaction and replay it instead of writing selectors by hand?

Yes. The workflow recorder captures actions against the UIA tree and emits a workflow.ts file you can then edit by hand, version in git, and run from CI. The recorded output is a sequence of createStep calls with selector strings as code, not a binary recording, so it diffs cleanly and an AI assistant can refactor it. The point is that the recording is a code artifact you own, not an opaque blob inside a vendor designer.

What is the smallest thing I can try before committing to this?

Two commands on a Windows box. First, install the MCP agent: claude mcp add terminator 'npx -y terminator-mcp-agent@latest'. Then open SAP Logon (or Oracle Forms) and ask your assistant to call get_window_tree on the running window. You will get back a JSON tree of every reachable control with role, name, AutomationId. That is the same tree the selector engine walks. If you do not see your target field in that tree, no framework will, and the conversation is about JAB, scripting, or a Citrix publishing decision. If you do, the rest is selector strings.

terminatorDesktop automation SDK
© 2026 terminator. All rights reserved.

How did this page land for you?

React to reveal totals

Comments ()

Leave a comment to see what others are saying.

Public and anonymous. No signup.