sap_gui_scripting 0.0.2 copy "sap_gui_scripting: ^0.0.2" to clipboard
sap_gui_scripting: ^0.0.2 copied to clipboard

True multi-threaded SAP GUI Automation for Dart & Flutter (Windows). Native C++/COM bridge with STA dispatcher enabling parallel SAP session scripting via Dart isolates. Provides 71 typed GUI componen [...]

sap_gui_scripting #

License: MIT Platform: Windows Dart SDK

True Multi-threaded SAP GUI Automation for Dart & Flutter (Windows).

A high-performance bridge between Dart and the SAP GUI Scripting API. Built on a native C++/COM core with STA (Single-Threaded Apartment) architecture, enabling parallel execution of multiple scripts across different SAP sessions — without blocking the main thread.


Why sap_gui_scripting? #

Traditional SAP GUI Scripting (VBScript, PowerShell, Python) runs on a single thread via COM, meaning you can only automate one session at a time. This package breaks that limitation:

Traditional SAP Scripting sap_gui_scripting
Parallel sessions No (single-threaded COM) Yes (6+ sessions in parallel)
Language VBScript / PowerShell / Python Dart & Flutter
Session pooling Manual Automatic via SapOrchestrator
Type safety Late-binding, runtime errors Static types, compile-time checks
Isolates N/A Each script runs in a Dart isolate
Mockable No Yes (ISapApi / ISapObject interfaces)
Use cases Simple macros Bulk extraction, RPA, Flutter desktop apps

Architecture #

┌─────────────────────────────────────────────────────────────┐
│                      DART LAYER                              │
│  ┌─────────────┐   ┌──────────┐   ┌──────────┐             │
│  │ Orchestrator │──▶│ Isolate 1│──▶│ Script A │ (Session 1) │
│  │  (Session    │   ├──────────┤   ├──────────┤             │
│  │   Pool)      │──▶│ Isolate 2│──▶│ Script B │ (Session 2) │
│  │              │   ├──────────┤   ├──────────┤             │
│  │  acquire()   │──▶│ Isolate N│──▶│ Script N │ (Session N) │
│  │  release()   │   └──────────┘   └──────────┘             │
│  └──────┬───────┘                                           │
│         │ FFI (dart:ffi)                                    │
├─────────┼───────────────────────────────────────────────────┤
│         ▼           C++ / COM LAYER (v4.dll)                │
│  ┌──────────────────────────────────────┐                   │
│  │     static ComStaDispatcher          │                   │
│  │  ┌────────────────────────────────┐  │                   │
│  │  │  STA Thread (single instance)  │  │                   │
│  │  │  g_objects map (shared)        │  │                   │
│  │  │  COM marshaling (CoInitialize) │  │                   │
│  │  └────────────────────────────────┘  │                   │
│  └──────────────────────────────────────┘                   │
├─────────────────────────────────────────────────────────────┤
│                     SAP GUI Scripting API                   │
│               (SAP GUI for Windows process)                 │
└─────────────────────────────────────────────────────────────┘

Three-layer isolation model:

  1. Dart LayerSapOrchestrator manages a session pool and spawns isolates per script via Isolate.spawn().
  2. Isolation Layer — Each script runs in its own isolate, reusing a pre-connected COM root handle.
  3. Native Layer — A single shared ComStaDispatcher in v4.dll provides one STA thread for the entire process, enabling true parallel access to SAP sessions.

Features #

  • True Multi-threading — Run scripts in parallel using Dart Isolates (not async/await on a single thread).
  • Session PoolingSapOrchestrator automatically creates and reuses SAP sessions (configurable up to 12+).
  • Intuitive API — Familiar find*() pattern for SAP developers: findCTextField(), findButton(), startTransaction(), etc.
  • 71 Typed ComponentsGuiButton, GuiTextField, GuiTableControl, GuiGridView (ALV), GuiTree, GuiToolbar, GuiMenu, GuiCalendar, GuiChart, and many more — all with compile-time type safety.
  • Robust Memory Management — C++ core safely manages COM lifecycle; Dart Finalizer handles garbage collection.
  • Mockable ArchitectureISapApi and ISapObject interfaces enable unit testing without a live SAP connection.
  • 360+ Unit Tests — Comprehensive test coverage for the FFI bridge and all GUI component wrappers.

Prerequisites #

Requirement Details
Windows OS SAP GUI Scripting is Windows-only
SAP GUI installed SAP Logon application on the machine
Scripting enabled (server) RZ11sapgui/user_scripting = TRUE
Scripting enabled (client) SAP GUI Options → Accessibility & Scripting → Scripting → Enable Scripting
MSVC (Visual Studio) Required to compile v4.dll
Dart SDK >=3.10.3

Installation #

1. Add the dependency #

dependencies:
  sap_gui_scripting: ^1.0.0

2. Compile the native DLL #

Compile the C++ bridge with MSVC:

cl /LD v4.cpp /EHsc /std:c++17 ole32.lib oleaut32.lib /out:v4.dll

The source files are located in lib/cpp_implementations/.

3. Place the DLL #

Ensure v4.dll is either:

  • In the same directory as your Dart/Flutter executable, or
  • Added to your system PATH environment variable

For Flutter Windows apps, place it in build\windows\x64\runner\Release\ alongside your .exe.


Quick Start #

Script (Worker) #

Define your automation logic as a top-level function:

import 'package:sap_gui_scripting/sap_orchestrator/script_runner.dart';

void getCustomerName(Map<String, dynamic> msg) async {
  await runScriptSafely<String>(msg, (session, args) async {
    session.startTransaction('XD03');

    // Find text field and set value
    session.findCTextField('wnd[0]/usr/ctxtRF02D-KUNNR')?.text = args.toString();

    // Press the search button
    session.findButton('wnd[0]/tbar[0]/btn[0]')?.press();

    // Read the customer name
    String? name = session
        .findTextField('wnd[0]/usr/subSUBTAB:SAPLXD04:0101/txtKNA1-NAME1')
        ?.text;

    session.endTransaction();
    return name ?? 'Not found';
  });
}

Tip: Always return to the main menu with session.endTransaction() so the session can be reused.

Orchestrator (Main) #

import 'package:sap_gui_scripting/sap_gui_scripting.dart';

void main() async {
  final orchestrator = SapOrchestrator();
  await orchestrator.initialize(maxSessions: 6);

  // Run multiple scripts in parallel
  final f1 = orchestrator.runScript<String>(getCustomerName, '10025');
  final f2 = orchestrator.runScript<String>(getCustomerName, '10026');
  final f3 = orchestrator.runScript<String>(getCustomerName, '10027');

  final results = await Future.wait([f1, f2, f3]);
  print('Results: $results'); // ['ACME Corp', 'Globex Inc', 'Initech']
}

Usage Patterns #

Flutter Desktop App #

class SapService {
  final orchestrator = SapOrchestrator();
  bool _ready = false;

  Future<void> init() async {
    _ready = await orchestrator.initialize(maxSessions: 12);
  }

  Future<String> readCustomer(String number) {
    return orchestrator.runScript<String>(_readCustomerScript, number);
  }
}

// Must be a top-level or static method
void _readCustomerScript(Map<String, dynamic> msg) async {
  await runScriptSafely<String>(msg, (session, args) async {
    session.startTransaction('XD03');
    session.findCTextField('wnd[0]/usr/ctxtRF02D-KUNNR')?.text = args.toString();
    session.findButton('wnd[0]/tbar[0]/btn[0]')?.press();
    final name = session.findTextField('wnd[0]/usr/subSUBTAB:SAPLXD04:0101/txtKNA1-NAME1')?.text;
    session.endTransaction();
    return name ?? 'Not found';
  });
}

Bulk Data Extraction (RPA) #

void main() async {
  final orchestrator = SapOrchestrator();
  await orchestrator.initialize(maxSessions: 6);

  final customers = ['10001', '10002', '10003', ...]; // 100+ customers

  // Process in batches of 6 (your pool size)
  for (final batch in _chunk(customers, 6)) {
    final futures = batch.map((id) =>
      orchestrator.runScript<String>(extractCustomerData, id));
    final results = await Future.wait(futures);
    _saveToDatabase(results);
  }
}

Table / Grid Extraction #

void extractTableData(Map<String, dynamic> msg) async {
  await runScriptSafely<List<Map<String, String>>>(msg, (session, args) async {
    session.startTransaction('SE16N');
    session.findCTextField('wnd[0]/usr/ctxtGD-TABLECLASS')?.text = 'KNA1';
    session.findButton('wnd[0]/tbar[1]/btn[8]')?.press();

    final grid = session.findGridView('wnd[0]/usr/cntlGRID1/shellcont/shell');
    if (grid == null) return [];

    final data = <Map<String, String>>[];
    for (int row = 0; row < grid.rowCount; row++) {
      data.add({
        'kunnr': grid.getCellValue(row, 'KUNNR') ?? '',
        'name1': grid.getCellValue(row, 'NAME1') ?? '',
        'ort01': grid.getCellValue(row, 'ORT01') ?? '',
      });
    }

    session.endTransaction();
    return data;
  });
}

Fire-and-Forget (No Result Needed) #

void saveChanges(Map<String, dynamic> msg) async {
  await runScriptSafely<void>(msg, (session, args) async {
    session.findButton('wnd[0]/tbar[0]/btn[11]')?.press(); // Save
    // No return value needed
  });
}

API Reference #

SapOrchestrator #

The central session pool and script dispatcher.

Member Description
SapOrchestrator() Singleton factory
initialize({int maxSessions = 6}) Connect to SAP, create session pool. Returns Future<bool>
runScript<T>(entryPoint, args) Spawn a script in an isolate. Returns Future<T>
isInitialized Whether the pool is ready
isInitializing Whether initialization is in progress
freeSessionCount Number of free sessions available
lastError Last error message
maxSessions Configured pool size
maxWaiting Max callers allowed to wait (default 20)

runScriptSafely & useSapSession #

Helper functions for writing scripts that run inside isolates.

// Always wrap your script logic:
Future<void> myScript(Map<String, dynamic> msg) async {
  await runScriptSafely<T>(msg, (session, args) async {
    // session = GuiSession (your SAP session)
    // args    = user-provided argument (dynamic)
    return /* T */;
  });
}

GuiSession (Core Session API) #

Method Description
startTransaction(String tcode) Start a transaction code
endTransaction() Return to SAP main menu
sendCommand(String cmd) Send an OK code
createSession() Create a new SAP session
findById(String id) Find any element by SAP ID
findById<T>(String id) Find and type-check any element
findButton(String id) Find a button
findCTextField(String id) Find a CText field
findTextField(String id) Find a text field
findGridView(String id) Find an ALV Grid
findTableControl(String id) Find a table control
findTree(String id) Find a tree control
findComboBox(String id) Find a combo box
findCheckBox(String id) Find a checkbox
findToolbar(String id) Find a toolbar
findStatusbar(String id) Find a status bar
findMenu(String id) Find a menu
... 40+ find*() methods available

GuiComponent Type Hierarchy #

GuiComponent (id, name, type, typeAsNumber, parent)
├── GuiVComponent (+ setFocus, visualize, text, tooltip, dimensions)
│   ├── GuiButton (press, emphasized)
│   ├── GuiTextField (caretPosition, displayedText, maxLength, etc.)
│   ├── GuiCTextField
│   ├── GuiPasswordField
│   ├── GuiOkCodeField
│   ├── GuiLabel
│   ├── GuiCheckBox
│   ├── GuiRadioButton
│   ├── GuiStatusPane
│   ├── GuiComboBox / GuiComboBoxControl / GuiComboBoxEntry
│   └── GuiVContainer → see below
│
├── GuiContainer (+ children, 40+ find*() methods)
│   ├── GuiApplication (connections, versions, openConnection)
│   ├── GuiConnection (sessions, closeConnection)
│   ├── GuiSession (info, activeWindow, start/endTransaction, sendCommand)
│   ├── GuiMainWindow (resizeWorkingPane, bar visibility)
│   ├── GuiFrameWindow
│   ├── GuiModalWindow
│   ├── GuiMessageWindow
│   ├── GuiBox / GuiContainerShell / GuiCustomControl
│   ├── GuiSimpleContainer / GuiScrollContainer / GuiSplitterContainer
│   ├── GuiUserArea
│   ├── GuiTab / GuiTabStrip
│   ├── GuiScrollbar / GuiToolbar / GuiTitlebar / GuiStatusbar
│   ├── GuiMenu / GuiMenubar
│   ├── GuiSessionInfo / GuiStatusBarLink
│   ├── GuiVHViewSwitch / GuiInputFieldControl
│   └── GuiVContainer → extends both GuiContainer & GuiVComponent
│       ├── GuiShell (has context menu support)
│       │   ├── GuiTree (node navigation, checkboxes)
│       │   ├── GuiGridView (ALV Grid — rows, columns, cell values)
│       │   ├── GuiCalendar
│       │   ├── GuiChart / GuiBarChart / GuiSapChart
│       │   ├── GuiNetChart
│       │   ├── GuiHTMLViewer
│       │   ├── GuiEAIViewer2D / GuiEAIViewer3D
│       │   ├── GuiPicture
│       │   ├── GuiOfficeIntegration
│       │   ├── GuiToolbarControl
│       │   ├── GuiGOSShell
│       │   └── GuiSplit (SplitterShell)
│       ├── GuiTableControl / GuiTableRow / GuiTableColumn
│       ├── GuiTextedit / GuiStage
│       ├── GuiDialogShell / GuiDockShell
│       ├── GuiGraphAdapt
│       └── GuiColorSelector

Mocking & Testing #

The package exposes ISapApi and ISapObject interfaces, enabling unit tests without a live SAP connection:

import 'package:mocktail/mocktail.dart';
import 'package:sap_gui_scripting/sap_gui_scripting.dart';

class MockSapObject extends Mock implements ISapObject {}

void main() {
  test('GuiButton press calls obj.press()', () {
    final mock = MockSapObject();
    final button = GuiButton(mock);

    when(() => mock.press()).thenReturn(null);

    button.press();

    verify(() => mock.press()).called(1);
  });
}

Troubleshooting #

Problem Solution
DLL not found Ensure v4.dll is in the same folder as your .exe or in PATH
Sap_Connect returns 0 Check SAP GUI is running and scripting is enabled
No SAP connections available Log into at least one SAP system in SAP Logon
Script hangs/timeout Check maxWaiting is not exceeded; reduce concurrent scripts
Type mismatch errors Verify SAP element IDs match expected component types
Session creation fails Check server-side scripting is enabled (RZ11)
Isolate communication error Ensure your entry point is a top-level or static function

Contributing #

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Development Setup #

# Install dependencies
dart pub get

# Run tests
dart test

# Run coverage
dart run test_cov_console

Running the Example #

cd example
flutter run -d windows

License #

MIT — See the LICENSE file for details.


Disclaimer #

This package is not affiliated, associated, authorized, or officially endorsed by SAP SE.



ESPAÑOL #

sap_gui_scripting #

License: MIT Platform: Windows Dart SDK

Automatización SAP GUI Multi-hilo real para Dart & Flutter (Windows).

Un puente de alto rendimiento entre Dart y la API de SAP GUI Scripting. Construido sobre un núcleo nativo C++/COM con arquitectura STA (Single-Threaded Apartment), permitiendo la ejecución en paralelo de múltiples scripts en diferentes sesiones de SAP, sin bloquear el hilo principal.


¿Por qué sap_gui_scripting? #

El scripting tradicional de SAP GUI (VBScript, PowerShell, Python) se ejecuta en un solo hilo a través de COM, lo que significa que solo puedes automatizar una sesión a la vez. Este paquete rompe esa limitación:

SAP Scripting Tradicional sap_gui_scripting
Sesiones en paralelo No (COM single-threaded) Sí (6+ sesiones en paralelo)
Lenguaje VBScript / PowerShell / Python Dart & Flutter
Pool de sesiones Manual Automático con SapOrchestrator
Seguridad de tipos Late-binding, errores en runtime Tipos estáticos, verificaciones en compilación
Isolates N/A Cada script se ejecuta en un isolate Dart
Mockeable No Sí (interfaces ISapApi / ISapObject)
Casos de uso Macros simples Extracción masiva, RPA, apps Flutter de escritorio

Arquitectura #

┌─────────────────────────────────────────────────────────────┐
│                     CAPA DART                               │
│  ┌─────────────┐   ┌──────────┐   ┌──────────┐             │
│  │ Orchestrator │──▶│ Isolate 1│──▶│ Script A │ (Sesión 1)  │
│  │  (Pool de    │   ├──────────┤   ├──────────┤             │
│  │   sesiones)  │──▶│ Isolate 2│──▶│ Script B │ (Sesión 2)  │
│  │              │   ├──────────┤   ├──────────┤             │
│  │  acquire()   │──▶│ Isolate N│──▶│ Script N │ (Sesión N)  │
│  │  release()   │   └──────────┘   └──────────┘             │
│  └──────┬───────┘                                           │
│         │ FFI (dart:ffi)                                    │
├─────────┼───────────────────────────────────────────────────┤
│         ▼          CAPA C++ / COM (v4.dll)                  │
│  ┌──────────────────────────────────────┐                   │
│  │     static ComStaDispatcher          │                   │
│  │  ┌────────────────────────────────┐  │                   │
│  │  │  STA Thread (instancia única)  │  │                   │
│  │  │  g_objects map (compartido)    │  │                   │
│  │  │  COM marshaling (CoInitialize) │  │                   │
│  │  └────────────────────────────────┘  │                   │
│  └──────────────────────────────────────┘                   │
├─────────────────────────────────────────────────────────────┤
│                 SAP GUI Scripting API                       │
│            (proceso SAP GUI for Windows)                    │
└─────────────────────────────────────────────────────────────┘

Modelo de tres capas de aislamiento:

  1. Capa DartSapOrchestrator gestiona un pool de sesiones y lanza isolates por script vía Isolate.spawn().
  2. Capa de Aislamiento — Cada script corre en su propio isolate, reutilizando un handle COM raíz pre-conectado.
  3. Capa Nativa — Un único ComStaDispatcher compartido en v4.dll provee un hilo STA para todo el proceso, permitiendo acceso paralelo real a sesiones SAP.

Características #

  • Multi-hilo Real — Ejecuta scripts en paralelo usando Isolates de Dart (no solo async/await en un hilo).
  • Pool de SesionesSapOrchestrator crea y reutiliza sesiones SAP automáticamente (configurable hasta 12+).
  • API Intuitiva — Patrón familiar find*() para desarrolladores SAP: findCTextField(), findButton(), startTransaction(), etc.
  • 71 Componentes TipadosGuiButton, GuiTextField, GuiTableControl, GuiGridView (ALV), GuiTree, GuiToolbar, GuiMenu, GuiCalendar, GuiChart, y muchos más — todos con seguridad de tipos en compilación.
  • Gestión de Memoria Robusta — El núcleo C++ gestiona el ciclo de vida de COM de forma segura; Finalizer de Dart maneja la recolección de basura.
  • Arquitectura Mockeable — Interfaces ISapApi e ISapObject permiten pruebas unitarias sin conexión SAP real.
  • 360+ Tests Unitarios — Cobertura de pruebas completa para el puente FFI y todos los wrappers de componentes.

Requisitos Previos #

Requisito Detalles
Windows OS SAP GUI Scripting solo está disponible en Windows
SAP GUI instalado SAP Logon instalado en la máquina
Scripting habilitado (servidor) RZ11sapgui/user_scripting = TRUE
Scripting habilitado (cliente) SAP GUI → Opciones → Accesibilidad y Scripting → Scripting → Habilitar Scripting
MSVC (Visual Studio) Necesario para compilar v4.dll
Dart SDK >=3.10.3

Instalación #

1. Añade la dependencia #

dependencies:
  sap_gui_scripting: ^1.0.0

2. Compila la DLL nativa #

Compila el puente C++ con MSVC:

cl /LD v4.cpp /EHsc /std:c++17 ole32.lib oleaut32.lib /out:v4.dll

Los archivos fuente están en lib/cpp_implementations/.

3. Ubica la DLL #

Asegúrate de que v4.dll esté:

  • En el mismo directorio que tu ejecutable Dart/Flutter, o
  • Añadida a la variable de entorno PATH del sistema

Para apps Flutter Windows, colócala en build\windows\x64\runner\Release\ junto a tu .exe.


Inicio Rápido #

Script (Worker) #

Define tu lógica de automatización como una función de nivel superior:

import 'package:sap_gui_scripting/sap_orchestrator/script_runner.dart';

void obtenerNombreCliente(Map<String, dynamic> msg) async {
  await runScriptSafely<String>(msg, (session, args) async {
    session.startTransaction('XD03');

    // Buscar campo de texto y establecer valor
    session.findCTextField('wnd[0]/usr/ctxtRF02D-KUNNR')?.text = args.toString();

    // Presionar el botón de búsqueda
    session.findButton('wnd[0]/tbar[0]/btn[0]')?.press();

    // Leer el nombre del cliente
    String? nombre = session
        .findTextField('wnd[0]/usr/subSUBTAB:SAPLXD04:0101/txtKNA1-NAME1')
        ?.text;

    session.endTransaction();
    return nombre ?? 'No encontrado';
  });
}

Consejo: Vuelve siempre al menú principal con session.endTransaction() para que la sesión pueda ser reutilizada.

Orquestador (Main) #

import 'package:sap_gui_scripting/sap_gui_scripting.dart';

void main() async {
  final orchestrator = SapOrchestrator();
  await orchestrator.initialize(maxSessions: 6);

  // Ejecutar múltiples scripts en paralelo
  final f1 = orchestrator.runScript<String>(obtenerNombreCliente, '10025');
  final f2 = orchestrator.runScript<String>(obtenerNombreCliente, '10026');
  final f3 = orchestrator.runScript<String>(obtenerNombreCliente, '10027');

  final resultados = await Future.wait([f1, f2, f3]);
  print('Resultados: $resultados'); // ['ACME Corp', 'Globex Inc', 'Initech']
}

Patrones de Uso #

App Flutter de Escritorio #

class SapService {
  final orchestrator = SapOrchestrator();
  bool _listo = false;

  Future<void> init() async {
    _listo = await orchestrator.initialize(maxSessions: 12);
  }

  Future<String> leerCliente(String numero) {
    return orchestrator.runScript<String>(_scriptLeerCliente, numero);
  }
}

// Debe ser una función top-level o static
void _scriptLeerCliente(Map<String, dynamic> msg) async {
  await runScriptSafely<String>(msg, (session, args) async {
    session.startTransaction('XD03');
    session.findCTextField('wnd[0]/usr/ctxtRF02D-KUNNR')?.text = args.toString();
    session.findButton('wnd[0]/tbar[0]/btn[0]')?.press();
    final nombre = session.findTextField('wnd[0]/usr/subSUBTAB:SAPLXD04:0101/txtKNA1-NAME1')?.text;
    session.endTransaction();
    return nombre ?? 'No encontrado';
  });
}

Extracción Masiva de Datos (RPA) #

void main() async {
  final orchestrator = SapOrchestrator();
  await orchestrator.initialize(maxSessions: 6);

  final clientes = ['10001', '10002', '10003', ...]; // 100+ clientes

  // Procesar en lotes de 6 (tamaño del pool)
  for (final lote in _agrupar(clientes, 6)) {
    final futures = lote.map((id) =>
      orchestrator.runScript<String>(extraerDatosCliente, id));
    final resultados = await Future.wait(futures);
    _guardarEnBaseDeDatos(resultados);
  }
}

Extracción de Tablas / Grids #

void extraerDatosTabla(Map<String, dynamic> msg) async {
  await runScriptSafely<List<Map<String, String>>>(msg, (session, args) async {
    session.startTransaction('SE16N');
    session.findCTextField('wnd[0]/usr/ctxtGD-TABLECLASS')?.text = 'KNA1';
    session.findButton('wnd[0]/tbar[1]/btn[8]')?.press();

    final grid = session.findGridView('wnd[0]/usr/cntlGRID1/shellcont/shell');
    if (grid == null) return [];

    final datos = <Map<String, String>>[];
    for (int row = 0; row < grid.rowCount; row++) {
      datos.add({
        'kunnr': grid.getCellValue(row, 'KUNNR') ?? '',
        'name1': grid.getCellValue(row, 'NAME1') ?? '',
        'ort01': grid.getCellValue(row, 'ORT01') ?? '',
      });
    }

    session.endTransaction();
    return datos;
  });
}

Fire-and-Forget (Sin Resultado) #

void guardarCambios(Map<String, dynamic> msg) async {
  await runScriptSafely<void>(msg, (session, args) async {
    session.findButton('wnd[0]/tbar[0]/btn[11]')?.press(); // Guardar
    // No se necesita devolver un valor
  });
}

Referencia de API #

SapOrchestrator #

El pool central de sesiones y despachador de scripts.

Miembro Descripción
SapOrchestrator() Singleton
initialize({int maxSessions = 6}) Conecta a SAP y crea el pool de sesiones. Retorna Future<bool>
runScript<T>(entryPoint, args) Lanza un script en un isolate. Retorna Future<T>
isInitialized Si el pool está listo
isInitializing Si la inicialización está en progreso
freeSessionCount Número de sesiones libres disponibles
lastError Último mensaje de error
maxSessions Tamaño configurado del pool
maxWaiting Máximo de llamadas en espera (por defecto 20)

runScriptSafely & useSapSession #

Funciones auxiliares para escribir scripts que se ejecutan dentro de isolates.

// Siempre envuelve tu lógica de script:
Future<void> miScript(Map<String, dynamic> msg) async {
  await runScriptSafely<T>(msg, (session, args) async {
    // session = GuiSession (tu sesión SAP)
    // args    = argumento proporcionado por el usuario (dynamic)
    return /* T */;
  });
}

GuiSession (API Principal de Sesión) #

Método Descripción
startTransaction(String tcode) Inicia una transacción
endTransaction() Vuelve al menú principal de SAP
sendCommand(String cmd) Envía un comando OK
createSession() Crea una nueva sesión SAP
findById(String id) Busca cualquier elemento por ID SAP
findById<T>(String id) Busca y verifica el tipo de cualquier elemento
findButton(String id) Busca un botón
findCTextField(String id) Busca un campo CText
findTextField(String id) Busca un campo de texto
findGridView(String id) Busca una ALV Grid
findTableControl(String id) Busca un table control
findTree(String id) Busca un tree control
findComboBox(String id) Busca un combo box
findCheckBox(String id) Busca un checkbox
findToolbar(String id) Busca una barra de herramientas
findStatusbar(String id) Busca una barra de estado
findMenu(String id) Busca un menú
... 40+ métodos find*() disponibles

Jerarquía de Tipos GuiComponent #

GuiComponent (id, name, type, typeAsNumber, parent)
├── GuiVComponent (+ setFocus, visualize, text, tooltip, dimensions)
│   ├── GuiButton (press, emphasized)
│   ├── GuiTextField (caretPosition, displayedText, maxLength, etc.)
│   ├── GuiCTextField
│   ├── GuiPasswordField
│   ├── GuiOkCodeField
│   ├── GuiLabel
│   ├── GuiCheckBox
│   ├── GuiRadioButton
│   ├── GuiStatusPane
│   ├── GuiComboBox / GuiComboBoxControl / GuiComboBoxEntry
│   └── GuiVContainer → ver abajo
│
├── GuiContainer (+ children, 40+ métodos find*())
│   ├── GuiApplication (connections, versions, openConnection)
│   ├── GuiConnection (sessions, closeConnection)
│   ├── GuiSession (info, activeWindow, start/endTransaction, sendCommand)
│   ├── GuiMainWindow (resizeWorkingPane, visibilidad de barras)
│   ├── GuiFrameWindow
│   ├── GuiModalWindow
│   ├── GuiMessageWindow
│   ├── GuiBox / GuiContainerShell / GuiCustomControl
│   ├── GuiSimpleContainer / GuiScrollContainer / GuiSplitterContainer
│   ├── GuiUserArea
│   ├── GuiTab / GuiTabStrip
│   ├── GuiScrollbar / GuiToolbar / GuiTitlebar / GuiStatusbar
│   ├── GuiMenu / GuiMenubar
│   ├── GuiSessionInfo / GuiStatusBarLink
│   ├── GuiVHViewSwitch / GuiInputFieldControl
│   └── GuiVContainer → extiende ambos GuiContainer y GuiVComponent
│       ├── GuiShell (soporte de menú contextual)
│       │   ├── GuiTree (navegación de nodos, checkboxes)
│       │   ├── GuiGridView (ALV Grid — filas, columnas, valores de celda)
│       │   ├── GuiCalendar
│       │   ├── GuiChart / GuiBarChart / GuiSapChart
│       │   ├── GuiNetChart
│       │   ├── GuiHTMLViewer
│       │   ├── GuiEAIViewer2D / GuiEAIViewer3D
│       │   ├── GuiPicture
│       │   ├── GuiOfficeIntegration
│       │   ├── GuiToolbarControl
│       │   ├── GuiGOSShell
│       │   └── GuiSplit (SplitterShell)
│       ├── GuiTableControl / GuiTableRow / GuiTableColumn
│       ├── GuiTextedit / GuiStage
│       ├── GuiDialogShell / GuiDockShell
│       ├── GuiGraphAdapt
│       └── GuiColorSelector

Mocking y Testing #

El paquete expone las interfaces ISapApi e ISapObject, permitiendo pruebas unitarias sin conexión SAP real:

import 'package:mocktail/mocktail.dart';
import 'package:sap_gui_scripting/sap_gui_scripting.dart';

class MockSapObject extends Mock implements ISapObject {}

void main() {
  test('GuiButton.press llama a obj.press()', () {
    final mock = MockSapObject();
    final button = GuiButton(mock);

    when(() => mock.press()).thenReturn(null);

    button.press();

    verify(() => mock.press()).called(1);
  });
}

Solución de Problemas #

Problema Solución
DLL no encontrada Asegúrate de que v4.dll esté en la misma carpeta que tu .exe o en el PATH
Sap_Connect devuelve 0 Verifica que SAP GUI esté en ejecución y el scripting habilitado
No SAP connections available Inicia sesión en al menos un sistema SAP en SAP Logon
El script se bloquea Verifica que maxWaiting no sea excedido; reduce scripts concurrentes
Errores de tipo (type mismatch) Verifica que los IDs de elementos SAP coincidan con los tipos de componente esperados
Fallo al crear sesiones Verifica que el scripting esté habilitado en el servidor (RZ11)
Error de comunicación entre isolates Asegúrate de que el entry point sea una función top-level o static

Contribuciones #

Las pull requests son bienvenidas. Para cambios mayores, por favor abre un issue primero para discutir lo que te gustaría cambiar.

Configuración de Desarrollo #

# Instalar dependencias
dart pub get

# Ejecutar tests
dart test

# Ejecutar cobertura
dart run test_cov_console

Ejecutar el Ejemplo #

cd example
flutter run -d windows

Licencia #

MIT — Ver el archivo LICENSE para más detalles.


Este paquete no está afiliado, asociado, autorizado ni respaldado oficialmente por SAP SE.

5
likes
140
points
6
downloads

Documentation

Documentation
API reference

Publisher

verified publisherjavivc.site

Weekly Downloads

True multi-threaded SAP GUI Automation for Dart & Flutter (Windows). Native C++/COM bridge with STA dispatcher enabling parallel SAP session scripting via Dart isolates. Provides 71 typed GUI component wrappers, session pooling, and a mockable architecture for RPA and bulk extraction.

Homepage
Repository (GitHub)
View/report issues

Topics

#sap #automation #rpa #win32 #ffi

License

MIT (license)

Dependencies

ffi, image, path, win32

More

Packages that depend on sap_gui_scripting