Skip to Content

Hello community,

at the beginning of this year I presented here, here and here different possibilities to use SAPs .NET Connector (NCo) in the context of the scripting language PowerShell. Now with new experience and knowledge I can say that the use of this combination is very profitably. You can try different programming situations fast, without a special IDE. Also you can use it to automate a lot of things, e.g. to download and compare data (customizing on different systems). The PowerShell ISE (Integrated Script Environment) with the integrated debugger offers a good range of functions, e.g. like syntax highlighting and code completion. All in all I can recommend PowerShell unlimited. As a further outlook for the future, a combination of SAP GUI Scripting, NCo and PowerShell seems very interesting. We will see…

Here now two more examples. The first shows how to ping an SAP system via RFC_PING and the build-in ping from NCo. The second shows how to get system via the function module RFC_SYSTEM_INFO. The code is commented and I think easy to understand. It shows, in conjunction with the links above, all variants of parameters.

1st example – Ping

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

  <#
    .Synopsis
      Calls PING of an SAP system.
    .Description
      Calls the function module RFC_PING and the build-in function
      Ping of the .NET connector.
  #>

  #-Sub Load-NCo--------------------------------------------------------
    Function Load-NCo {

      $ScriptDir = $PSScriptRoot

      $Size = [System.IntPtr]::Size
      If ($Size -eq 4) {
        $Path = $ScriptDir + "\x86\"
      }
      ElseIf ($Size -eq 8) {
        $Path = $ScriptDir + "\x64\"
      }

      [Reflection.Assembly]::LoadFile($Path + "sapnco.dll") > $Null
      [Reflection.Assembly]::LoadFile($Path + "sapnco_utils.dll") > $Null

    }

  #-Function Get-Destination--------------------------------------------
    Function Get-Destination {

      #-Connection parameters-------------------------------------------
        $cfgParams = New-Object SAP.Middleware.Connector.RfcConfigParameters
        $cfgParams.Add("NAME", "TEST")
        $cfgParams.Add("ASHOST", "ABAP")
        $cfgParams.Add("SYSNR", "00")
        $cfgParams.Add("CLIENT", "001")
        $cfgParams.Add("USER", "BCUSER")

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

      Return [SAP.Middleware.Connector.RfcDestinationManager]::GetDestination($cfgParams)

    }

  #-Sub Execute-Ping----------------------------------------------------
    Function Execute-Ping () {

      $destination = Get-Destination

      #-Metadata--------------------------------------------------------
        [SAP.Middleware.Connector.IRfcFunction]$rfcFunction =
          $destination.Repository.CreateFunction("RFC_PING")

      #-Variant 1: Call function module---------------------------------
        Try {
          $rfcFunction.Invoke($destination)
          Write-Host "Ping successful"
        }
        Catch {
          Write-Host "Exception" $_.Exception.Message "occured"
        }

      #-Variant 2: Call build-in function-------------------------------
        Try {
          $destination.Ping()
          Write-Host "Ping successful"
        }
        Catch {
          Write-Host "Exception" $_.Exception.Message "occured"
        }

    }

  #-Sub Main------------------------------------------------------------
    Function Main () {
      If ($PSVersionTable.PSVersion.Major -ge 3) {
        Load-NCo
        Execute-Ping
      }
    }

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

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

2nd example – RFC_SYSTEM_INFO

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

  <#
    .Synopsis
      Calls RFC_SYSTEM_INFO of an SAP system.
    .Description
      Calls the function module RFC_SYSTEM_INFO and writes the result
      on the screen.
  #>

  #-Sub Load-NCo--------------------------------------------------------
    Function Load-NCo {

      $ScriptDir = $PSScriptRoot

      $Size = [System.IntPtr]::Size
      If ($Size -eq 4) {
        $Path = $ScriptDir + "\x86\"
      }
      ElseIf ($Size -eq 8) {
        $Path = $ScriptDir + "\x64\"
      }

      [Reflection.Assembly]::LoadFile($Path + "sapnco.dll") > $Null
      [Reflection.Assembly]::LoadFile($Path + "sapnco_utils.dll") > $Null

    }

  #-Function Get-Destination--------------------------------------------
    Function Get-Destination {

      #-Connection parameters-------------------------------------------
        $cfgParams = New-Object SAP.Middleware.Connector.RfcConfigParameters
        $cfgParams.Add("NAME", "TEST")
        $cfgParams.Add("ASHOST", "ABAP")
        $cfgParams.Add("SYSNR", "00")
        $cfgParams.Add("CLIENT", "001")
        $cfgParams.Add("USER", "BCUSER")

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

      Return [SAP.Middleware.Connector.RfcDestinationManager]::GetDestination($cfgParams)

    }

  #-Sub Get-SystemInfo--------------------------------------------------
    Function Get-SystemInfo () {

      $destination = Get-Destination

      #-Metadata--------------------------------------------------------
        [SAP.Middleware.Connector.IRfcFunction]$rfcFunction =
          $destination.Repository.CreateFunction("RFC_SYSTEM_INFO")

      #-Call function module--------------------------------------------
        Try {
          $rfcFunction.Invoke($destination)

          [SAP.Middleware.Connector.IRfcStructure]$Export =
            $rfcFunction.GetStructure("RFCSI_EXPORT")

          #-Get information---------------------------------------------
            Write-Host $Export.GetValue("RFCHOST")
            Write-Host $Export.GetValue("RFCSYSID")
            Write-Host $Export.GetValue("RFCDBHOST")
            Write-Host $Export.GetValue("RFCDBSYS")

        }
        Catch {
          Write-Host "Exception" $_.Exception.Message "occured"
        }

    }

  #-Sub Main------------------------------------------------------------
    Function Main () {
      If ($PSVersionTable.PSVersion.Major -ge 3) {
        Load-NCo
        Get-SystemInfo
      }
    }

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

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

3rd example – RFC_READ_TABLE

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

  <#
    .Synopsis
      Calls RFC_READ_TABLE of an SAP system.
    .Description
      Calls the function module RFC_READ_TABLE and writes the result
      on the screen.
  #>

  #-Sub Load-NCo--------------------------------------------------------
    Function Load-NCo {

      $ScriptDir = $PSScriptRoot

      If ([Environment]::Is64BitProcess) {
        $Path = $ScriptDir + "\x64\"
      }
      Else {
        $Path = $ScriptDir + "\x86\"
      }

      $File = $Path + "sapnco.dll"; Add-Type -Path $File
      $File = $Path + "sapnco_utils.dll"; Add-Type -Path $File

    }

  #-Function Get-Destination--------------------------------------------
    Function Get-Destination {

      #-Connection parameters-------------------------------------------
        $cfgParams = New-Object SAP.Middleware.Connector.RfcConfigParameters
        $cfgParams.Add("NAME", "TEST")
        $cfgParams.Add("ASHOST", "ABAP")
        $cfgParams.Add("SYSNR", "00")
        $cfgParams.Add("CLIENT", "001")
        $cfgParams.Add("USER", "BCUSER")

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

      Return [SAP.Middleware.Connector.RfcDestinationManager]::GetDestination($cfgParams)

    }
  
  #-Sub Read-Table------------------------------------------------------
    Function Read-Table ([String]$TableName) {

      $destination = Get-Destination

      #-Metadata--------------------------------------------------------
        $rfcFunction = `
          $destination.Repository.CreateFunction("RFC_READ_TABLE")

      #-Call function module--------------------------------------------
        Try {
          $rfcFunction.SetValue("QUERY_TABLE", $TableName)
          $rfcFunction.SetValue("DELIMITER", ";")

          $rfcFunction.Invoke($destination)

          [SAP.Middleware.Connector.IRfcTable]$Table = `
            $rfcFunction.GetTable("DATA")

          ForEach ($Line In $Table) {
            Write-Host $Line.GetValue("WA")
          }

        }
        Catch {
          Write-Host "Exception occured:`r`n" $_.Exception.Message
        }


    }

  #-Sub Main------------------------------------------------------------
    Function Main () {
      If ($PSVersionTable.PSVersion.Major -ge 5) {
        Load-NCo
        Read-Table "USR01"
      }
    }

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

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

4th example – RFC_READ_TABLE with JSON result

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

  <#
    .Synopsis
      Calls RFC_READ_TABLE of an SAP system.
    .Description
      Calls the function module RFC_READ_TABLE and writes the result
      in JSON on the screen.
  #>

  #-Sub Load-NCo--------------------------------------------------------
    Function Load-NCo {

      $ScriptDir = $PSScriptRoot

      If ([Environment]::Is64BitProcess) {
        $Path = $ScriptDir + "\x64\"
      }
      Else {
        $Path = $ScriptDir + "\x86\"
      }

      $File = $Path + "sapnco.dll"; Add-Type -Path $File
      $File = $Path + "sapnco_utils.dll"; Add-Type -Path $File

    }

  #-Function Get-Destination--------------------------------------------
    Function Get-Destination {

      #-Connection parameters-------------------------------------------
        $cfgParams = New-Object SAP.Middleware.Connector.RfcConfigParameters
        $cfgParams.Add("NAME", "TEST")
        $cfgParams.Add("ASHOST", "ABAP")
        $cfgParams.Add("SYSNR", "00")
        $cfgParams.Add("CLIENT", "001")
        $cfgParams.Add("USER", "BCUSER")

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

      Return [SAP.Middleware.Connector.RfcDestinationManager]::GetDestination($cfgParams)

    }
  
  #-Sub Read-Table------------------------------------------------------
    Function Read-Table-JSON ([String]$TableName, [Int]$RowCount) {

      $destination = Get-Destination

      #-Metadata--------------------------------------------------------
        $rfcFunction = `
          $destination.Repository.CreateFunction("RFC_READ_TABLE")

      #-Call function module--------------------------------------------
        Try {
          $rfcFunction.SetValue("QUERY_TABLE", $TableName)
          $rfcFunction.SetValue("DELIMITER", "~")
          $rfcFunction.SetValue("ROWCOUNT", $RowCount)

          $rfcFunction.Invoke($destination)

          $Header = New-Object System.Collections.ArrayList

          #-Get field names for the CSV header--------------------------
            [SAP.Middleware.Connector.IRfcTable]$Fields = `
              $rfcFunction.GetTable("FIELDS")
            ForEach ($Field In $Fields) {
              [Void]$Header.Add($Field.GetValue("FIELDNAME"))
            }

          #-Get table data line by line for CSV-------------------------
            [SAP.Middleware.Connector.IRfcTable]$Table = `
              $rfcFunction.GetTable("DATA")
            ForEach ($Line In $Table) {
              $CSV = $CSV + $Line.GetValue("WA") + "`r`n"
            }

          #-Convert CSV to JSON-----------------------------------------
            $JSON = $CSV | ConvertFrom-Csv -Delimiter "~" `
              -Header $Header | ConvertTo-Json

          Return $JSON

        }
        Catch {
          Write-Host "Exception occured:`r`n" $_.Exception.Message
        }


    }

  #-Sub Main------------------------------------------------------------
    Function Main () {
      If ($PSVersionTable.PSVersion.Major -ge 5) {
        Load-NCo
        Write-Host(Read-Table-JSON "SFLIGHT" 0)
      }
    }

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

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

If you like you can find the same functionality here, with SAP NetWeaver RFC SDK and FreeBASIC, to compare it.

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