I am trying to write a C# program that will automate a user's input into the SAP GUI (currently on version 7400.3.11.3364) using SAP's scripting API. I've done similar things in the past using VBA, but I'm struggling to get it working exactly how I want it to in C#. My end goal is to have a method that opens SAP (if it isn't already running), returns the GuiApplication object of SAP, and leaves SAP open after my program ends. I currently have it working in VBA, and I believe I had it working correctly in C# on a previous project when we were on SAP GUI version 7.3, but I'm not 100% sure
Here is the VBA Function I use:
Public Function GetSapApp() as GuiApplication
Dim Start as Date
If GetObject("SAPGUI") Is Nothing Then
Start = Now()
Shell "C:\Program Files (x86)\SAP\FrontEnd\SAPgui\saplogon.exe"
Do Until Not GetObject("SAPGUI") Is Nothing Or Now > (Start + TimeValue("00:01:00"))
DoEvents
Loop
If GetObject("SAPGUI") Is Nothing Then
MsgBox "Unable to detect SAP Scripting API. Please contact the developer."
End If
Set GetSapApp = GetObject("SAPGUI").GetScriptingEngine
End Function
And here are the different C# methods I've found while googling:
Below is what I'm currently using (the idea was inspired by this: https://www.codeproject.com/Questions/829500/How-do-I-connect-Csharp-to-SAP-GUI), but there are a couple issues with it. It doesn't seem to detect SAP if it is already open. Also, after my program runs, this SAP isn't detectable by any of our VBA macros.
private static GuiApplication GetSapApp() { try { object SapGuilRot = new CSapROTWrapper().GetROTEntry("SAPGUI"); return SapGuilRot.GetType().InvokeMember("GetScriptingEngine", System.Reflection.BindingFlags.InvokeMethod, null, SapGuilRot, null) as GuiApplication; } catch (Exception e) { try { string SapPath = "C:\\Program Files (x86)\\SAP\\FrontEnd\\SAPgui\\saplogon.exe"; if (File.Exists(SapPath)) { System.Diagnostics.Process.Start(SapPath); DateTime StartTime = DateTime.Now; object SapGuilRot = new CSapROTWrapper().GetROTEntry("SAPGUI"); while (SapGuilRot == null && 30 >= (DateTime.Now - StartTime).TotalSeconds) { SapGuilRot = new CSapROTWrapper().GetROTEntry("SAPGUI"); } return SapGuilRot.GetType().InvokeMember("GetScriptingEngine", System.Reflection.BindingFlags.InvokeMethod, null, SapGuilRot, null) as GuiApplication; } else { return null; } } catch { return null; } } }
Here is another option I've tried (per this answer on another SO post: https://stackoverflow.com/a/14205520/5134861), but it has the same first issue as above (doesn't detect if SAP is currently running), the SAP session that gets opened when you call the
OpenConnection
method looks different and then closes when my program is done running.private static GuiApplication GetSapApp() { return (GuiApplication)System.Activator.CreateInstance(Type.GetTypeFromProgID("SapGui.ScriptingCtrl.1")); }
And here is the last option I've tried, but I get a
Cannot create ActiveX component
error, despite having varified sapfewse.ocx is registered.private static GuiApplication GetSapApp() { object sap = Microsoft.VisualBasic.Interaction.GetObject("SAPGUI", ""); return sap.GetType().InvokeMember("GetScriptingEngine", System.Reflection.BindingFlags.InvokeMethod, null, sap, null) as GuiApplication; }
Any help and/or suggestions would be greatly appreciated.
Thanks in advance!