Skip to Content
Technical Articles
Author's profile photo Stefan Schnell

How To Use NCo With PowerShell: Client Apps (PowerShell uses .NET Connector)

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.

Assigned Tags

      1 Comment
      You must be Logged on to comment or reply to a post.
      Author's profile photo Lars Urban
      Lars Urban

      Hello Stefan,

      a liitle bit late, but thank you very much ! It´s a live saver ;D