Skip to Content

In some cases it is necessary with SAP GUI Scripting to loop over all existing connections and sessions. If a session is busy, which means the SAP GUI is waiting for data from the server, it is necessary to detect this situation, to avoid blocking the execution thread. For this case offers SAP GUI Scripting the property Busy of the GuiSession class. But in some cases blocks the property Children of the GuiConnection class, before it is possible to use Busy property.

The following code blocks the execution at line

$session = Get-Property $connection "Children" @($j)

The execution of the script is blocked until the session is available again.

#-Begin-----------------------------------------------------------------

  #-Includes------------------------------------------------------------
  ."$PSScriptRoot\COM.ps1"

  #-Sub Main------------------------------------------------------------
  Function Main() {

    $SapGuiAuto = Get-Object( , "SAPGUI")
    If ($SapGuiAuto -isnot [__ComObject]) {
      Exit
    }

    $application = Invoke-Method $SapGuiAuto "GetScriptingEngine"
    If ($application -isnot [__ComObject]) {
      Free-Object $SapGuiAuto
      Exit
    }

    For($i = 0; $i -lt $application.Children().Count(); $i++) {
      $connection = Get-Property $application "Children" @($i)
      For($j = 0; $j -lt $connection.Children().Count(); $j++) {
        $session = Get-Property $connection "Children" @($j)
        If ($session.Busy() -eq 1) {
          Continue
        }

      }
    }

    Free-Object $SapGuiAuto

  }

  #-Main----------------------------------------------------------------
  Main

#-End-------------------------------------------------------------------

 

Here another approach to bypass this situation:

#-Begin-----------------------------------------------------------------

  #-Includes------------------------------------------------------------
  ."$PSScriptRoot\COM.ps1"

  #-Sub Main------------------------------------------------------------
  Function Main() {

    $SapGuiAuto = Get-Object( , "SAPGUI")
    If ($SapGuiAuto -isnot [__ComObject]) {
      Exit
    }

    $application = Invoke-Method $SapGuiAuto "GetScriptingEngine"
    If ($application -isnot [__ComObject]) {
      Free-Object $SapGuiAuto
      Exit
    }

    $connections = Get-Property $application "Connections"
    ForEach ($connection In $connections) {
      $sessions = Get-Property $connection "Sessions"
      ForEach ($session In $sessions) {
        If ($session.Busy() -eq 1) {
          Continue
        }

      }
    }

    Free-Object $SapGuiAuto

  }

  #-Main----------------------------------------------------------------
  Main

#-End-------------------------------------------------------------------

Both sources do exactly the same, they loop over all connections and sessions. But in the secound source I use another method. I get all connections and sessions and loop over this. And with this approach works the Busy property as expected.

Enjoy it.

Cheers
Stefan

To report this post you need to login first.

2 Comments

You must be Logged on to comment or reply to a post.

  1. Márcio Vieira

    Hello Stefan,

    I have been trying to do a script to run multiple transactions in different windows, I found this article https://archive.sap.com/discussions/thread/3388231 which is already archived since it is the year 2013 now reading this topic on the property “Busy”, would it be possible to run multiple sessions simultaneously?

     

    Note: My scripts are in VBA or Autoit.

     

    Thank you very much

     

    Márcio.

     

    (0) 
  2. Stefan Schnell Post author

    Hello Márcio,

    sure it that possible. Here an example in PowerShell.

    #-Begin-----------------------------------------------------------------
    
    $ScriptBlock = {
      Param($sessionNumber);
    
      ."C:\Script\COM.ps1"
    
      $SapGuiAuto = Get-Object( , "SAPGUI")
      If ($SapGuiAuto -isnot [__ComObject]) {
        Exit
      }
    
      $application = Invoke-Method $SapGuiAuto "GetScriptingEngine"
      If ($application -isnot [__ComObject]) {
        Free-Object $SapGuiAuto
        Exit
      }
    
      $connection = Get-Property $application "Children"@(0)
      If ($connection -eq $Null) {
        Free-Object $SapGuiAuto
        Exit
      }
    
      $session = Get-Property $connection "Children"@($sessionNumber)
      If ($session -eq $Null) {
        Free-Object $SapGuiAuto
        Exit
      }
    
      for ($i = 1; $i -le 10; $i++) {
        $ID = Invoke-Method $session "findById" @("wnd[0]/tbar[0]/okcd")
        Set-Property $ID "text" @("/nse16")
        $ID = Invoke-Method $session "findById" @("wnd[0]")
        Invoke-Method $ID "sendVKey" @(0)
        $ID = Invoke-Method $session "findById" @("wnd[0]/usr/ctxtDATABROWSE-TABLENAME")
        Set-Property $ID "text" @("tfdir")
        $ID = Invoke-Method $session "findById" @("wnd[0]/usr/ctxtDATABROWSE-TABLENAME")
        Set-Property $ID "caretPosition" @(5)
        $ID = Invoke-Method $session "findById" @("wnd[0]")
        Invoke-Method $ID "sendVKey" @(0)
        $ID = Invoke-Method $session "findById" @("wnd[0]/tbar[1]/btn[31]")
        Invoke-Method $ID "press"
        $ID = Invoke-Method $session "findById" @("wnd[1]/tbar[0]/btn[0]")
        Invoke-Method $ID "press"
        $ID = Invoke-Method $session "findById" @("wnd[0]/tbar[0]/btn[3]")
        Invoke-Method $ID "press"
        $ID = Invoke-Method $session "findById" @("wnd[0]/tbar[0]/btn[3]")
        Invoke-Method $ID "press"
        Start-Sleep -Milliseconds 500
      }
    
      Free-Object $session
      Free-Object $connection
      Free-Object $application
      Free-Object $SapGuiAuto
    
    }
    
    Start-Job -ScriptBlock $ScriptBlock -ArgumentList 0;
    Start-Job -ScriptBlock $ScriptBlock -ArgumentList 1;
    
    #-End-------------------------------------------------------------------

    The ScriptBlock contains the script and with the commands Start-Job two scripts are running parallel. PowerShell offers fantastic possibilities to use background jobs. In my eyes it is not up to date anymore to realize those kinds of solutions in VBA. So you must realize solutions which have nothing to do with your business problem. To use this solution also in VBA you can use SAPIENS ActiveXPoSHV3, PowerShell access for VBScript/JScript developers – but you can use it also in VBA or AutoIt. You can find more information here. Here an example how to use it in VBA:

    Option Explicit
    
    Const OUTPUT_CONSOLE = 0
    Const OUTPUT_WINDOW = 1
    Const OUTPUT_BUFFER = 2
    
    Sub ParallelTest()
    
      Dim ActiveXPosh As ActiveXPoshV3.IActiveXPoSH
      Dim success As Boolean
      Dim PSScript As String
      Dim iFile As Integer: iFile = FreeFile
    
      Open "C:\Script\Test.ps1" For Input As #iFile
      PSScript = Input(LOF(iFile), iFile)
      Close #iFile
      
      Set ActiveXPosh = CreateObject("SAPIEN.ActiveXPoSHV3")
      success = ActiveXPosh.Init(vbFalse)
      If success <> 0 Then
        Debug.Print "Init failed"
        Exit Sub
      End If
        
      If ActiveXPosh.IsPowerShellInstalled Then
        ActiveXPosh.OutputMode = OUTPUT_BUFFER
        ActiveXPosh.Execute (PSScript)
        Debug.Print ActiveXPosh.OutputString
      Else
        Debug.Print "PowerShell not installed"
        Exit Sub
      End If
    
    End Sub

    Cheers
    Stefan

    (0) 

Leave a Reply