Skip to Content

Hello community,

in the context of a discussion I developed and presented a complete launch sequence of SAP GUI Scripting in VBScript. But for the future it seems better to use PowerShell, for reasons which I have described here. Now the equivalent in PowerShell script language:

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

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

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

      $OpenNewConnFlag = $false

      if (-Not (Get-Process saplogon -ErrorAction silentlycontinue)) {
        Start-Process "C:\Program Files (x86)\SAP\FrontEnd\SAPgui\saplogon.exe"
         do {
           Start-Sleep -Milliseconds 250
         } until(Get-Process | where {$_.mainWindowTitle -like "SAP Logon 740"})
      }
      $SapGuiAuto = Get-Object( , "SAPGUI")
      $application = Invoke-Method $SapGuiAuto "GetScriptingEngine"
      $connection = Get-Property $application "Children" @(0)
      if ($connection -eq $Null) {
        $OpenNewConnFlag = $true
        Invoke-Method $application "OpenConnectionByConnectionString" `
          @("/H/10.100.200.300/S/3200", $true) > $Null
        $connection = Get-Property $application "Children" @(0)
      }
      $session = Get-Property $connection "Children" @(0)

      if ($OpenNewConnFlag -eq $true) {
        $ID = Invoke-Method $session "findById" @("wnd[0]/usr/txtRSYST-MANDT")
        Set-Property $ID "Text" @("001")
        $ID = Invoke-Method $session "findById" @("wnd[0]/usr/txtRSYST-BNAME")
        Set-Property $ID "Text" @("BCUSER")
        $ID = Invoke-Method $session "findById" @("wnd[0]/usr/pwdRSYST-BCODE")
        Set-Property $ID "Text" @("minisap")
        $ID = Invoke-Method $session "findById" @("wnd[0]/usr/txtRSYST-LANGU")
        Set-Property $ID "Text" @("EN")
        $ID = Invoke-Method $session "findById" @("wnd[0]")
        Invoke-Method $ID "sendVKey" @(0)
      }

      Free-Object $session
      Free-Object $connection
      Free-Object $application
      Free-Object $SapGuiAuto

    }

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

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

Here now the facelifted COM include, which I introduced here:

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

  #-Load assembly-------------------------------------------------------
  [Reflection.Assembly]::LoadWithPartialName("Microsoft.VisualBasic") > $Null
  [Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") > $Null

  #-Function Create-Object----------------------------------------------
  Function Create-Object([String]$objectName) {
    try {
      New-Object -ComObject $objectName
    }
    catch {
      [Void] [System.Windows.Forms.MessageBox]::Show(
        "Can't create object", "Important hint", 0)
    }  
  }

  #-Function Get-Object-------------------------------------------------
  Function Get-Object([String]$pathName, [String]$class) {
    [Microsoft.VisualBasic.Interaction]::GetObject($pathName, $class)
  }

  #-Sub Free-Object-----------------------------------------------------
  Function Free-Object([__ComObject]$object) {
    [Void] [System.Runtime.Interopservices.Marshal]::ReleaseComObject($object)
  }

  #-Function Get-Property-----------------------------------------------
  Function Get-Property([__ComObject]$object, [String]$propertyName,
    $propertyParameters) {
    $objectType = [System.Type]::GetType($object)
    $objectType.InvokeMember($propertyName,
      [System.Reflection.Bindingflags]::GetProperty,
      $null, $object, $propertyParameters)
  }

  #-Sub Set-Property----------------------------------------------------
  Function Set-Property([__ComObject]$object, [String]$propertyName, 
  	$propertyValue) {
    $objectType = [System.Type]::GetType($object)
    [Void] $objectType.InvokeMember($propertyName,
      [System.Reflection.Bindingflags]::SetProperty,
      $null, $object, $propertyValue)
  }

  #-Function Invoke-Method----------------------------------------------
  Function Invoke-Method([__ComObject]$object, [String]$methodName, 
  	$methodParameters) {
    $objectType = [System.Type]::GetType($object)
    $output = $objectType.InvokeMember($methodName,
      "InvokeMethod", $NULL, $object, $methodParameters)
    if ( $output ) { $output }
  }

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

Hint: This code is a different perspective from the solution here.

 

And here a further development of the approach above:

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

  If ($PSVersionTable.PSVersion.Major -eq 2) {
    $PSScriptRoot = Split-Path $($MyInvocation.InvocationName) -Parent
  } 

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

  #-Function Logon------------------------------------------------------
  Function Logon() {

    $SecPasswd = Read-Host -Prompt "Passwort" -AsSecureString
    $ptrPasswd = [Runtime.InteropServices.Marshal]::SecureStringToBStr($SecPasswd)
    $Passwd = [Runtime.InteropServices.Marshal]::PtrToStringBStr($ptrPasswd)

    Invoke-Method $application "OpenConnectionByConnectionString" `
      @("/H/10.100.200.300/S/3200", $True) > $Null
    $connection = Get-Property $application "Children" @(0)
    $session = Get-Property $connection "Children" @(0)
    $ID = Invoke-Method $session "findById" @("wnd[0]/usr/txtRSYST-MANDT")
    Set-Property $ID "Text" @("001")
    $ID = Invoke-Method $session "findById" @("wnd[0]/usr/txtRSYST-BNAME")
    Set-Property $ID "Text" @("BCUSER")
    $ID = Invoke-Method $session "findById" @("wnd[0]/usr/pwdRSYST-BCODE")
    Set-Property $ID "Text" @($Passwd)
    $ID = Invoke-Method $session "findById" @("wnd[0]/usr/txtRSYST-LANGU")
    Set-Property $ID "Text" @("EN")
    $ID = Invoke-Method $session "findById" @("wnd[0]")
    Invoke-Method $ID "sendVKey" @(0)

    $connection
    $session
  }

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

    $Found = $False

    If (-Not (Get-Process saplogon -ErrorAction silentlycontinue)) {
      Start-Process "C:\Program Files (x86)\SAP\FrontEnd\SAPgui\saplogon.exe"
       do {
         Start-Sleep -Milliseconds 250
       } until(Get-Process | where {$_.mainWindowTitle -like "SAP Logon 740"})
    }

    $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"
    If ($connections -isnot [__ComObject]) { 
      $Ret = Logon
      $connection = $Ret[0]
      $session = $Ret[1]
    } Else {

      $connections = Get-Property $application "Connections"

      :found
      ForEach ($connection In $connections) {
        $sessions = Get-Property $connection "Sessions"
        ForEach ($session In $sessions) {
          If ($session.Busy() -eq 1) {
            Continue
          }
          $sessionInfo = Get-Property $session "Info"
          $SID = Get-Property $sessionInfo "SystemName"
          $TAC = Get-Property $sessionInfo "Transaction"
          If ($SID -eq "NSP" -and $TAC -eq "SESSION_MANAGER") {
            $Found = $True
            Break found
          }
        }
      }

      If ($Found = $False) {
        $Ret = Logon
        $connection = $Ret[0]
        $session = $Ret[1]
      }

    }

    #-------------------------------------------------------------------
    #-
    #- In the variables $connection and $session are now the required
    #- information
    #-
    #-------------------------------------------------------------------



    Free-Object $SapGuiAuto

  }

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

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

 

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