Using PowerShell to connect to SAP is not something you see a lot of on the web, thus I though I would post my experience with it.
Over the past weeks I have been off the grid working had on an custom integration into SAP to facilitate FIM 2010 R2 password sync via SSPR. Due to various reasons we were forced to build the integration rather than using the packages Microsoft Web Services management agent. In the process we also took a view that in order to try make the project as simple as possible to support in the future that we would try to use a PowerShell management agent to complete the integration. As such we decided to build the MA using the “Granfeldt PowerShell Management Agent (MA)”
I will creating a follow-up post on how exactly we made the entire solution functional, but this post I wanted to dedicate to a SAP web service proxy error I ran into while using the PowerShell New-WebServiceProxy cmdlet in order to consume the web service.
If you are not familiar with the New-WebServiceProxy, please stop reading this article and check you the following: (it will change you life)
SAP Enterprise Service Setup
We configured the SAP Enterprise Service (sproxy and soamanager) to consume two functional groups in order to expose the default ECC BAPI’s. Note that in the standard FIM Web Services guide for ECC, you are required to create a new functional group that contains copies of the standard BAPI’s. This is not ideal since you could have to manually update these in the future if you load any new support packs to ECC. We opted to create two web services that publishes BAPI as per their function groups.
These meant that BAPI_USER_GETLIST, BAPI_USER_GETDETAIL, BAPI_USER_UNLOCK and BAPI_USER_CHANGE were in one web service while SUSR_USER_CHANGE_PASSWORD_RFC was in a separate web service (since these functions are in separate functional groups). Using this approach meant we did not require copies of the BAPI’s but rather we could publish the internal version.
This left us with two web service en-points:
- The user management web services (BAPI_USER_GETLIST, BAPI_USER_GETDETAIL, BAPI_USER_UNLOCK and BAPI_USER_CHANGE)
- The password reset web service (SUSR_USER_CHANGE_PASSWORD_RFC)
Using PowerShell to connect to SAP
When we implemented the web service using the PowerShell New-WebServiceProxy, we followed the standard syntax as shown below:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
|# SAP proxy variables
|$uriUserManagement = "http://sapserver/sap/bc/srt/wsdl/flv_10002A111AD1/bndg_url/sap/bc/srt/rfc/sap/zfimconnector/010/zfimconnector_user/zfimconnector_user?sap-client=010"
|$uriUserManagementNamespace = "SAP"
|$uriUserManagementClass = "SAP_WSDL"
|# Create a secure credential to pass to the WS-Proxy
|$secpasswd = ConvertTo-SecureString $password -AsPlainText -Force
|$credential = New-Object System.Management.Automation.PSCredential ($username, $secpasswd)
|# Create web services proxy object
|$proxyUser = New-WebServiceProxy -Uri $uriUserManagement -Credential $credential -Class $uriUserManagementClass -Namespace $uriUserManagementNamespace
New-WebServiceProxy : Could not load file or assembly
The problem came in when I tried to connect to the second web service using PowerShell. I received a really useless error that look as follows.
$proxyUser = New-WebServiceProxy -Uri $uriUserManagement -Credential $credential -Class $uriUserManagementClass -Namespace $uriUserManagementNamespace New-WebServiceProxy : Could not load file or assembly 'file:///%TEMP%\asqe3oyx.dll' or one of its dependencies. The system cannot find the file specified. At line:1 char:7 + $ws = New-WebServiceProxy -Uri 'http://sapserver/sap/bc/srt/wsdl ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [New-WebServiceProxy], FileNotFoundException + FullyQualifiedErrorId : System.IO.FileNotFoundException,Microsoft.PowerShell.Commands.NewWebServiceProxy
Nothing I tried to do on the PowerShell side could let me solve this problem. Suggestions included using a different web service, closing and opening PowerShell and resolving a duplicate method conflict. None of these were specific enough to pursue and none had anything remotely to do with using this in a SAP scenario.
The error message will always have a different file name, but the rest will be the same.
New-WebServiceProxy : Could not load file or assembly xxx or one of its dependencies. The system cannot find the file specified
The only option we had was to look at the SAP configuration. This is what we found.
One the SAP side out two web services had two different “Namespace” configuration settings when we compared them. This and the fact that the BAPI in each web service proxy was in different function groups was the only difference that we could see. The one was set to “urn:sap-com:document:sap:soap:functions:mc-style” and the other “urn:sap-com:document:sap:rfc:functions”.
I am not sure what the difference between the two namespace types are technically, but it appears that it has to do with how SAP publishes the functions within the BAPI via the web service proxy. In order to create a proxy of the BAPI using the correct namespace you need to correctly add the BAPI via the function group when creating the proxy (in sproxy). The difference is subtle, but it made all the difference. The screenshot below shows the step when the BAPI is added to the proxy. Initially we used the “BAPI” method of adding the BAPI and the second time we added the BAPI by browsing vir the “Function Group” method.
Once we re-created the two SAP proxies using the method above, both the Namespace values were “urn:sap-com:document:sap:rfc:functions” and this allows me to connect to both of the web services. Small fix, huge troubleshooting to find. Hope this helps someone using either any CLR language or PowerShell to avoid a lot of pain.