py_canoe.core.application.Application

Main interface to CANoe Application via COM automation.

Source code in src\py_canoe\core\application.py
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
def __init__(self, enable_events: bool = True) -> None:
    self.CANOE_APP_NAME = "CANoe.Application"
    self._enable_events = enable_events
    self.com_object: Any = None
    self.application_events: Union[ApplicationEvents, Any] = None
    self.capl_function_objects = object()
    self.user_capl_functions = tuple()
    # Register IMessageFilter to suppress "Server Busy" dialogs and auto-retry
    # rejected COM calls. The filter stays active for the Application's lifetime.
    self._message_filter = COMRetryMessageFilter()
    self._message_filter.register()
    # Lazy wrapper caches: only the wrappers that hold mutable state fetched
    # from CANoe are cached as singletons:
    #   - Measurement registers a COM event sink (WithEvents) that must stay
    #     alive and unique for the Application's lifetime.
    #   - Configuration and Networks cache data fetched when a configuration
    #     is loaded (test environments/modules, diagnostic devices) that is
    #     consumed by later calls; they are re-created on each configuration
    #     load (see _setup_post_configuration_loading).
    # All other wrappers are stateless facades over read-only COM properties
    # and are created on demand.
    self._configuration: Union[Configuration, None] = None
    self._networks: Union[Networks, None] = None
    self._measurement: Union[Measurement, None] = None

capl property

Returns the CAPL object (read-only, mirrors COM Application.CAPL).

channel_mapping_name property writable

Sets or returns the application name used to map application channels to real existing Vector network interface channels.

configuration property

Returns the Configuration object (read-only, mirrors COM Application.Configuration).

The wrapper is cached because it holds test environment/module data that is fetched when a configuration is loaded and consumed by later calls.

environment property

Returns the Environment object (read-only, mirrors COM Application.Environment).

full_name property

Returns full path of the currently loaded CANoe configuration.

measurement property

Returns the Measurement object (read-only, mirrors COM Application.Measurement).

The wrapper is cached because it registers a COM event sink that must stay alive and unique for the Application's lifetime.

name property

Returns name of the currently loaded CANoe configuration.

networks property

Returns the Networks object (read-only, mirrors COM Application.Networks).

The wrapper is cached because it holds diagnostic devices data that is fetched when a configuration is loaded and consumed by later calls.

path property

Returns the directory path of the currently loaded CANoe configuration.

performance property

Returns the Performance object (read-only, mirrors COM Application.Performance).

simulation property

Returns the Simulation object (read-only, mirrors COM Application.Simulation).

system property

Returns the System object (read-only, mirrors COM Application.System).

ui property

Returns the UI object (read-only, mirrors COM Application.UI).

version property

Returns the Version object (read-only, mirrors COM Application.Version).

visible property writable

Returns whether the CANoe application window is visible.

attach_to_active_application()

Attach to an already running CANoe application instance.

Source code in src\py_canoe\core\application.py
353
354
355
356
357
358
359
360
361
362
363
364
365
366
def attach_to_active_application(self) -> bool:
    """Attach to an already running CANoe application instance."""
    try:
        self._launch_application()
        if self.com_object:
            logger.info("Successfully attached to active CANoe application ")
            self._setup_post_configuration_loading()
            return True
        else:
            logger.error("Failed to attach to active CANoe application")
            return False
    except Exception as e:
        logger.error(f"Error attaching to active CANoe application: {e}")
        return False

bus(bus_type=BusType.CAN)

Returns a Bus object for the given bus type.

This mirrors the COM Application.Bus([type]) property. The Bus wrapper is stateless (it only wraps the COM Bus object), so a fresh wrapper is created on each call.

Parameters:
  • bus_type (BusType, default: CAN ) –

    The bus type as a BusType enum member. Defaults to BusType.CAN.

Source code in src\py_canoe\core\application.py
103
104
105
106
107
108
109
110
111
112
113
def bus(self, bus_type: BusType = BusType.CAN) -> Bus:
    """Returns a Bus object for the given bus type.

    This mirrors the COM Application.Bus([type]) property. The Bus wrapper is
    stateless (it only wraps the COM Bus object), so a fresh wrapper is
    created on each call.

    Args:
        bus_type: The bus type as a BusType enum member. Defaults to BusType.CAN.
    """
    return Bus(self.com_object.GetBus(bus_type.name))

new(auto_save=False, prompt_user=False, timeout=5)

Create a new empty CANoe configuration.

Source code in src\py_canoe\core\application.py
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
def new(self, auto_save: bool = False, prompt_user: bool = False, timeout: int = 5) -> bool:
    """Create a new empty CANoe configuration."""
    self._launch_application()
    status = False
    try:
        logger.info("Opening new empty CANoe configuration...")
        self.com_object.New(auto_save, prompt_user)
        if self._enable_events:
            cond = lambda: self.application_events.OPENED
        else:
            cond = lambda: self.com_object.FullName != ""
        status = DoEventsUntil(cond, timeout, "New CANoe configuration")
        if status:
            logger.info("New empty CANoe configuration Opened")
            self._setup_post_configuration_loading()
        return status
    except Exception as e:
        logger.error(f"Error creating new configuration: {e}")
        status = False
        return status

new_configuration_from_yaml(configuration_path, path_to_yaml_folder, scenario_name='')

Creates a new configuration from an existing venvironment.yaml or venvironment-basic.yaml.

Parameters:
  • configuration_path (str) –

    The path where the new configuration should be located including the configuration name.

  • path_to_yaml_folder (str) –

    The path to the directory which contains the YAML file.

  • scenario_name (str, default: '' ) –

    The scenario for which a configuration should be created.

Source code in src\py_canoe\core\application.py
185
186
187
188
189
190
191
192
193
194
def new_configuration_from_yaml(self, configuration_path: str, path_to_yaml_folder: str, scenario_name: str = "") -> None:
    """Creates a new configuration from an existing venvironment.yaml or venvironment-basic.yaml.

    Args:
        configuration_path: The path where the new configuration should be
            located including the configuration name.
        path_to_yaml_folder: The path to the directory which contains the YAML file.
        scenario_name: The scenario for which a configuration should be created.
    """
    self.com_object.NewConfigurationFromYaml(configuration_path, path_to_yaml_folder, scenario_name)

open(canoe_cfg, visible=True, auto_save=True, prompt_user=False, timeout=5)

Open a CANoe configuration file (.cfg) in a new or existing CANoe instance.

Source code in src\py_canoe\core\application.py
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
def open(self, canoe_cfg: str | Path, visible: bool = True, auto_save: bool = True, prompt_user: bool = False, timeout: int = 5) -> bool:
    """Open a CANoe configuration file (.cfg) in a new or existing CANoe instance."""
    self._launch_application()
    status = False
    try:
        self.visible = visible
        logger.info("Opening CANoe configuration ...")
        canoe_cfg_str = str(Path(canoe_cfg).resolve())
        self.com_object.Open(canoe_cfg_str, auto_save, prompt_user)
        if self._enable_events:
            cond = lambda: self.application_events.OPENED
        else:
            cond = lambda: self.com_object.FullName.lower() == canoe_cfg_str.lower()
        status = DoEventsUntil(cond, timeout, "Open CANoe configuration")
        if status:
            logger.info(f"CANoe Configuration {canoe_cfg} Opened")
            self._setup_post_configuration_loading()
        return status
    except Exception as e:
        logger.error(f"Error opening configuration: {e}")
        status = False
        return status

open_config(canoe_cfg, auto_save=True, prompt_user=False, timeout=60)

Switch to a different CANoe configuration without restarting CANoe.

This method switches configurations in an already-running CANoe instance. Use this when CANoe is already running and you want to load a different .cfg file.

For starting CANoe with a configuration from scratch, use open() instead.

Parameters:
  • canoe_cfg (str | Path) –

    Path to the CANoe configuration (.cfg) file.

  • auto_save (bool, default: True ) –

    If True, automatically save the current configuration before switching.

  • prompt_user (bool, default: False ) –

    If True, prompt user for confirmation before switching.

  • timeout (int, default: 60 ) –

    Maximum time to wait for configuration to load (seconds).

Returns:
  • bool

    True if configuration was successfully loaded, False otherwise.

Source code in src\py_canoe\core\application.py
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
def open_config(self, canoe_cfg: str | Path, auto_save: bool = True, prompt_user: bool = False, timeout: int = 60) -> bool:
    """Switch to a different CANoe configuration without restarting CANoe.

    This method switches configurations in an already-running CANoe instance.
    Use this when CANoe is already running and you want to load a different .cfg file.

    For starting CANoe with a configuration from scratch, use open() instead.

    Args:
        canoe_cfg: Path to the CANoe configuration (.cfg) file.
        auto_save: If True, automatically save the current configuration before switching.
        prompt_user: If True, prompt user for confirmation before switching.
        timeout: Maximum time to wait for configuration to load (seconds).

    Returns:
        True if configuration was successfully loaded, False otherwise.
    """
    import time as _time
    status = False
    try:
        abs_path = str(Path(canoe_cfg).resolve())
        logger.info(f"Switching to CANoe configuration: {abs_path}")

        # Reset OPENED flag before calling Open
        self.application_events.OPENED = False

        # Call COM Open() to switch configuration
        self.com_object.Open(abs_path, auto_save, prompt_user)

        if self._enable_events:
            status = DoEventsUntil(
                lambda: self.application_events.OPENED and self.configuration.full_name.lower() == abs_path.lower(),
                timeout,
                f"Switch to configuration {canoe_cfg}"
            )
        else:
            # Poll FullName without PumpWaitingMessages
            poll_deadline = _time.monotonic() + timeout
            while _time.monotonic() < poll_deadline:
                try:
                    if self.configuration.full_name.lower() == abs_path.lower():
                        status = True
                        break
                except Exception:
                    pass
                _time.sleep(0.2)

        if status:
            logger.info(f"Configuration switched successfully to {canoe_cfg}")
            self._setup_post_configuration_loading()
        else:
            logger.warning(f"Configuration switch timed out after {timeout}s")

        return status
    except Exception as e:
        logger.error(f"Error switching configuration: {e}")
        return False

pump_messages()

Pump COM messages to prevent blocking.

This is a thin wrapper around pythoncom.PumpWaitingMessages(). Use this in custom wait loops to keep COM responsive.

Example

while not ready(): app.pump_messages() time.sleep(0.1)

Source code in src\py_canoe\core\application.py
426
427
428
429
430
431
432
433
434
435
436
437
def pump_messages(self) -> None:
    """Pump COM messages to prevent blocking.

    This is a thin wrapper around pythoncom.PumpWaitingMessages().
    Use this in custom wait loops to keep COM responsive.

    Example:
        >>> while not ready():
        >>>     app.pump_messages()
        >>>     time.sleep(0.1)
    """
    pythoncom.PumpWaitingMessages()

quit(timeout=5)

Quit the CANoe application gracefully.

Source code in src\py_canoe\core\application.py
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
def quit(self, timeout: int = 5) -> bool:
    """Quit the CANoe application gracefully."""
    status = False
    try:
        if self._configuration is not None and self.configuration.modified:
            self.configuration.modified = False
        # Do NOT release event sinks before Quit(). CANoe fires OnExit (and
        # potentially OnStop) as part of its internal shutdown sequence after
        # Quit() is called. Releasing sinks beforehand leaves CANoe with a
        # dangling vtable pointer → access violation → crash dialog.
        # Sinks are released in the finally block after CANoe has shut down.
        self.com_object.Quit()
        status = DoEventsUntil(lambda: self.application_events.QUIT, timeout, "Quit CANoe application")
        if status:
            logger.info("CANoe Application Quit Successfully.")
        return status
    except Exception as e:
        logger.error(f"Error during CANoe quit: {e}")
        status = False
        return status
    finally:
        self._release_event_sinks()