Skip to Content

Hello community,

here a SAP GUI Scripting Recorder in PowerShell scripting language.

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

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

      [Reflection.Assembly]::LoadWithPartialName("Microsoft.VisualBasic") > $Null
      [Reflection.Assembly]::LoadFile($PSScriptRoot + "\SAPFEWSELib.dll") > $Null

      $SapGuiAuto = [Microsoft.VisualBasic.Interaction]::GetObject("SAPGUI")
      If ($SapGuiAuto -eq $Null) {
        Break
      }

      $Application = $SapGuiAuto.GetType().InvokeMember("GetScriptingEngine",
        [System.Reflection.Bindingflags]::InvokeMethod,
        $null, $SapGuiAuto, $null, $null, $null, $null)
      [SAPFEWSELib.GuiApplication]$Application =
        [System.Runtime.InteropServices.Marshal]::CreateWrapperOfType($Application,
        [SAPFEWSELib.GuiApplicationClass])
      If ($Application -eq $Null) {
        Break
      }

      $Connection = $Application.Children.Item(1)
      [SAPFEWSELib.GuiConnectionClass]$Connection =
        [System.Runtime.InteropServices.Marshal]::CreateWrapperOfType($Connection,
        [SAPFEWSELib.GuiConnectionClass])
      If ($Connection -eq $Null) {
        Break
      }

      $Session = $Connection.Children.Item(0)
      [SAPFEWSELib.GuiSession]$Session =
        [System.Runtime.InteropServices.Marshal]::CreateWrapperOfType($Session,
        [SAPFEWSELib.GuiSessionClass])
      If ($Session -eq $Null) {
        Break
      }

      $Session.Record = $True
      Register-ObjectEvent -InputObject $Session -EventName "Change" -SourceIdentifier "Action" > $Null

      While ($true) {
        Write-Host "Waiting for event..."
        $Event = Wait-Event -SourceIdentifier "Action" -Timeout 10
        If ($Event -eq $Null) {
          Write-Host "No event received for 10 seconds."
          Break
        }
        #$event.SourceArgs
        Write-Host "ID: " $event.SourceArgs[1].Id
        Write-Host "Type / Method / Parameter: " $event.SourceArgs[2].SyncRoot
        Remove-Event -SourceIdentifier "Action"
      }
      Unregister-Event -SourceIdentifier "Action"
      $Session.Record = $False
    }

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

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

As you can see I use the normal SAP GUI Scripting commands to get the application, connection and session. I set the property record of the session object to true and register the change event to record my activities. Now in the while loop, which exits after 10 seconds if no event is fired, I catch the parameters via $event.SourceArgs. Last but not least I unregister the event and set record to false.

Here the result of one activity:

Waiting for event...

Name                   : ses[0]
Type                   : GuiSession
TypeAsNumber           : 12
ContainerType          : True
Id                     : /app/con[1]/ses[0]
Parent                 : System.__ComObject
Children               : System.__ComObject
ActiveWindow           : System.__ComObject
Info                   : System.__ComObject
Record                 : True
TestToolMode           : 0
RecordFile             :
Busy                   : False
IsActive               : True
SaveAsUnicode          : True
ShowDropdownKeys       : False
PassportTransactionId  : 0A64C954920015101318093545917000
PassportPreSystemId    : NSP/nsp_NSP_00
PassportSystemId       : NSP/nsp_NSP_00
ErrorList              : System.__ComObject
AccEnhancedTabChain    : False
AccSymbolReplacement   : False
IsListBoxActive        : False
ListBoxTop             : 0
ListBoxLeft            : 0
ListBoxWidth           : 0
ListBoxHeight          : 0
ListBoxCurrEntryTop    : 0
ListBoxCurrEntryLeft   : 0
ListBoxCurrEntryWidth  : 0
ListBoxCurrEntryHeight : 0
ListBoxCurrEntry       : -1
ProgressPercent        : 0
ProgressText           :
SuppressBackendPopups  :

Name                   : shell
Type                   : GuiShell
TypeAsNumber           : 122
ContainerType          : True
Id                     : /shell
Parent                 :
Length                 : 3
LongLength             : 3
Rank                   : 1
SyncRoot               : {SP, selectedNode, F00002}
IsReadOnly             : False
IsFixedSize            : True
IsSynchronized         : False
Count                  : 3

Waiting for event...

No event received for 10 seconds.

As you can see you get a lot of information. Important is the ID and the SyncRoot. With these information you can build a scripting recorder of your mind.

Here is another (actual) variant with NWBC Interop.SAPFEWSELib.dll:

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

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

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

      [Reflection.Assembly]::LoadWithPartialName("Microsoft.VisualBasic") > $Null
      [Reflection.Assembly]::LoadFile("C:\Program Files (x86)\SAP\NWBC50\Interop.SAPFEWSELib.dll") > $Null

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

      $Application = Invoke-Method $SapGuiAuto "GetScriptingEngine"
      [Interop.SAPFEWSELib.GuiApplication]$Application =
        [System.Runtime.InteropServices.Marshal]::CreateWrapperOfType($Application,
        [Interop.SAPFEWSELib.GuiApplicationClass])
      If ($Application -isnot [System.__ComObject]) {
        Break
      }

      $Connection = $Application.Children.Item(0)
      If ($Connection -eq $Null) {
        Break
      }
      Else {
        [Interop.SAPFEWSELib.GuiConnectionClass]$Connection =
          [System.Runtime.InteropServices.Marshal]::CreateWrapperOfType($Connection,
          [Interop.SAPFEWSELib.GuiConnectionClass])
      }

      $Session = $Connection.Children.Item(0)
      If ($Session -eq $Null) {
        Break
      }
      Else {
        [Interop.SAPFEWSELib.GuiSession]$Session =
          [System.Runtime.InteropServices.Marshal]::CreateWrapperOfType($Session,
          [Interop.SAPFEWSELib.GuiSessionClass])
      }

      $Session.Record = $True
      Register-ObjectEvent -InputObject $Session -EventName "Change" -SourceIdentifier "Action" > $Null

      While ($true) {
        Write-Host "Waiting for event..."
        $Event = Wait-Event -SourceIdentifier "Action" -Timeout 10
        If ($Event -eq $Null) {
          Write-Host "No event received for 10 seconds."
          Break
        }
        [Interop.SAPFEWSELib.GuiSession]$RecSession =
          [System.Runtime.InteropServices.Marshal]::CreateWrapperOfType($event.SourceArgs[0],
          [Interop.SAPFEWSELib.GuiSessionClass])
        Write-Host ( $RecSession | Format-List | Out-String )
        #Without this line above delivers PowerShell with the command:
        #Write-Host ( $RecComponent | Select -ExpandProperty "ID" )
        #the error:
        #The data necessary to complete this operation is not yet available.
        #(Exception from HRESULT: 0x8000000A)
        [Interop.SAPFEWSELib.GuiComponent]$RecComponent =
          [System.Runtime.InteropServices.Marshal]::CreateWrapperOfType($event.SourceArgs[1],
          [Interop.SAPFEWSELib.GuiComponentClass])
        Write-Host ( $RecComponent | Format-List | Out-String )
        #Write-Host ( $RecComponent | Select -ExpandProperty "ID" )
        #Write-Host "Type / Method / Parameter: " $event.SourceArgs[2]
        Remove-Event -SourceIdentifier "Action"
      }

      Unregister-Event -SourceIdentifier "Action"
      $Session.Record = $False

    }

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

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

Here the result of one activity:

Waiting for event...

Name                   : ses[0]
Type                   : GuiSession
TypeAsNumber           : 12
ContainerType          : -1
Id                     : /app/con[0]/ses[0]
Parent                 : System.__ComObject
Children               : System.__ComObject
ActiveWindow           : System.__ComObject
Info                   : System.__ComObject
Record                 : -1
TestToolMode           : 0
RecordFile             : 
Busy                   : 0
IsActive               : -1
SaveAsUnicode          : -1
ShowDropdownKeys       : 0
PassportTransactionId  : 58266AFB639E8990E10000000A64C9A0
PassportPreSystemId    : NSP/nsp_NSP_00
PassportSystemId       : NSP/nsp_NSP_00
ErrorList              : System.__ComObject
AccEnhancedTabChain    : 0
AccSymbolReplacement   : 0
IsListBoxActive        : 0
ListBoxTop             : 0
ListBoxLeft            : 0
ListBoxWidth           : 0
ListBoxHeight          : 0
ListBoxCurrEntryTop    : 0
ListBoxCurrEntryLeft   : 0
ListBoxCurrEntryWidth  : 0
ListBoxCurrEntryHeight : 0
ListBoxCurrEntry       : -1
ProgressPercent        : 0
ProgressText           : 
SuppressBackendPopups  : 

Name          : btn[3]
Type          : GuiButton
TypeAsNumber  : 40
ContainerType : 0
Id            : /app/con[0]/ses[0]/wnd[0]/tbar[0]/btn[3]
Parent        : System.__ComObject

Waiting for event...

No event received for 10 seconds.

As you can see a tiny difference in the component object.

Enjoy it.

Cheers

Stefan

To report this post you need to login first.

Be the first to leave a comment

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

Leave a Reply