cancel
Showing results for 
Search instead for 
Did you mean: 

Beginner - Create a Visual Studio application console in .NET to interact with SAP

ptuga
Explorer

Hello,

This is my first raised question to the community.

I've just very recently found out that it is possible to record steps in SAP and save them to a vb file.

At the same time I also found out that, you can use an adapted code e.g. inside a VBA excel file and run it to create the same behavior as if you were pressing the run command in SAP for such a stored script.

This was a big thing to me because working in SAP and to have any possible interaction to it from the "outside" would be a mind changer.

I've since searched and searched for a way to create my interaction outside the VBA IDE and to use Visual Studio to run my code. So far, it was impossible to me to have it working. Errors after errors.

My question at this point, without having to keep spending time is simple: Can I assume this is even possible? Use a VS application to run C# or VB.NET to do the simplest thing like run a transaction in SAP from the outside?

I use Windows 10 - 64 bit and the SAP GUI for Windows release 7600.1.9.1160.

If anyone could provide me the feedback, I could then build up my knowledge and start asking step by step questions.

I have absolutely no knowledge about this topic. I'm familiar with C# and just a small bit on VB.NET, so, any gain from this point is a benefit. To be honest, there should be a lot of other people in the same conditions.

Please let me have your precious feedback.

Many thanks in advance.

Regards

moshenaveh
Community Manager
Community Manager
Welcome and thanks for visiting SAP Community to get answers to your questions. Check out our tutorial to get started in SAP Community: https://developers.sap.com/tutorials/community-start.html
By adding a picture to your profile you encourage readers to respond to your question. Learn more about your profile here: https://developers.sap.com/tutorials/community-profile.html

Accepted Solutions (1)

Accepted Solutions (1)

stefan_schnell
Active Contributor

ptuga

Hello Pedro,

welcome in the SAP Community.

In my opinion you have two possibilities to automate SAP activities via dotNET languages like C# or VBdotNET.

  1. Via SAP GUI Scripting, to automize via the UI, in this case SAP GUI for Windows.
  2. Via dotNET Connector (NCo), to automize via API, remote enabled function calls. The SAP NCo is part of the SAP GUI for Windows installation.

Here an SAP GUI Scripting example in VBdotNET, it opens TAC SE16 and shows the number of entries of the table TADIR:

'-Begin-----------------------------------------------------------------

Imports System
Imports Microsoft.VisualBasic

Public Module SAPGUIScripting
  Sub Main()

    Dim SapGuiAuto As Object
    Dim app As Object
    Dim connection As Object
    Dim session As Object

    Dim connectionNumber As Integer = 0
    Dim sessionNumber As Integer = 0

    Try
      SapGuiAuto = GetObject("SAPGUI")
      app = SapGuiAuto.GetScriptingEngine
      app.HistoryEnabled = False
      connection = app.Children(CInt(connectionNumber))
      If connection.DisabledByServer = True Then Exit Sub
      session = connection.Children(CInt(sessionNumber))
      If session.Info.IsLowSpeedConnection = True Then Exit Sub
    Catch
      Exit Sub
    End Try

'-Here begins your SAP GUI Scripting code-------------------------------
session.findById("wnd[0]/tbar[0]/okcd").text = "/nSE16"
session.findById("wnd[0]").sendVKey(0)
session.findById("wnd[0]/usr/ctxtDATABROWSE-TABLENAME").text = "TADIR"
session.findById("wnd[0]").sendVKey(0)
session.findById("wnd[0]/tbar[1]/btn[31]").press
'-Here ends your SAP GUI Scripting code---------------------------------

    app.HistoryEnabled = True

  End Sub

End Module

'-End-------------------------------------------------------------------

With VBdotNET you can use the recorded script from the Script Recording and Playback... menu item.

Here the same example in C#:

//-Begin----------------------------------------------------------------

using System;
using System.Reflection;
using System.Runtime.InteropServices;
using Microsoft.VisualBasic;

public class SAPGUIScripting {

  static dynamic InvokeMethod(object obj, string methodName, object[] methodParams = null) {
    return obj.GetType().InvokeMember(methodName, BindingFlags.InvokeMethod, null, obj, methodParams);
  }

  static dynamic GetProperty(object obj, string propertyName, object[] propertyParams = null) {
    return obj.GetType().InvokeMember(propertyName, BindingFlags.GetProperty, null, obj, propertyParams);
  }

  static dynamic SetProperty(object obj, string propertyName, object[] propertyParams = null) {
    return obj.GetType().InvokeMember(propertyName, BindingFlags.SetProperty, null, obj, propertyParams);
  }

  static void FreeObject(object obj) {
    Marshal.ReleaseComObject(obj);
  }

  static void Main() {

    object SapGuiAuto = null;
    object connection = null;
    object app = null;
    object session = null;

    int connectionNumber = 0;
    int sessionNumber = 0;

    try {
      SapGuiAuto = Interaction.GetObject("SAPGUI");
      app = InvokeMethod(SapGuiAuto, "GetScriptingEngine");
      SetProperty(app, "HistoryEnabled", new object[1]{false});
      connection = GetProperty(app, "Children", new object[1]{connectionNumber});
      if(GetProperty(connection, "DisabledByServer") == true) { return; }
      session = GetProperty(connection, "Children", new object[1]{sessionNumber});
      object info = GetProperty(session, "Info");
      if(GetProperty(info, "IsLowSpeedConnection") == true) { return; }
    } catch {
      return;
    }

    dynamic ID = null;

//-Here begins your SAP GUI Scripting code------------------------------
ID = InvokeMethod(session, "findById", new object[1]{"wnd[0]/tbar[0]/okcd"});
SetProperty(ID, "text", new object[1]{"/nSE16"});
ID = InvokeMethod(session, "findById", new object[1]{"wnd[0]"});
InvokeMethod(ID, "sendVKey", new object[1]{0});
ID = InvokeMethod(session, "findById", new object[1]{"wnd[0]/usr/ctxtDATABROWSE-TABLENAME"});
SetProperty(ID, "text", new object[1]{"TADIR"});
ID = InvokeMethod(session, "findById", new object[1]{"wnd[0]"});
InvokeMethod(ID, "sendVKey", new object[1]{0});
ID = InvokeMethod(session, "findById", new object[1]{"wnd[0]/tbar[1]/btn[31]"});
InvokeMethod(ID, "press");
//-Here ends your SAP GUI Scripting code--------------------------------

    SetProperty(app, "HistoryEnabled", new object[1]{true});

    FreeObject(session);
    FreeObject(connection);
    FreeObject(app);
    FreeObject(SapGuiAuto);

  }

}

//-End------------------------------------------------------------------

If you want to automize via API you can find more information about SAP NCo here.

Best regards
Stefan

ptuga
Explorer

Hi Stefan,

Many thanks for your answer. Much appreciated.

Being at the "zero" level on this topic, I don't even know where to begin!

VBdotNet is definitely not my strong and my likes (syntax) are more in line with C#. So, before anything I would like to re-ask the question: Can we use C#? How? I've read so many blogs where Windows 64 bit and some references don't work. A simplistic sample code pointing me in the right direction would be great. Something similar to your first example. Really useful and clean. I've created an application following that first example in VBdotNet (using a different transaction) and it worked like a charm. The strange thing was, I have not used the keyword "Import" for specific namespaces and have nor used/loaded any reference to the project, and still, it worked fine. Not sure exactly why. Could you please answer?

I'm not also very sure about your second example and what it is trying to achieve. Maybe you can just give me a hint?

I would also ask two other questions for now:

1. Can the message "A script is attempting to access SAP Gui" which also requires user prompt, be avoided?

2. Can we run the script having the "SAP Easy Access" window hidden? Same for the "SAP Logon 760" window?

I'll wait for your feedback in high expectations.

Kind regards,

Pedro

stefan_schnell
Active Contributor

ptuga

Hello Pedro,

thanks for your comment.

Yes, you can use C#. Both examples above doing exactly the same activities. To handle SAP GUI Scripting API via COM calls it is necessary to add the methods InvokeMethod, GetProperty, SetProperty etc.

This command in VBdotNET...

session.findById("wnd[0]/tbar[0]/okcd").text = "/nSE16"

... is exact the same as this command in C#.

ID = InvokeMethod(session, "findById", new object[1]{"wnd[0]/tbar[0]/okcd"});
SetProperty(ID, "text", new object[1]{"/nSE16"});

The use of the Imports in VBdotNET is depending from your development environment. I use a very minimalistic environment and here it is necessary to define the namespaces. I assume you use a more comfortable environment which add this dependencies automatically.

To your questions:

  1. Sure, disable in the SAP Logon options the notifications.

  2. SAP GUI Scripting works also if the windows are minimized.

Hope I have answered your question.

Best regards
Stefan

ptuga
Explorer
0 Kudos

Hi Stefan,

Thank you for your answers. Yes all clear.

Tried the settings (less annoying now when a scrip runs). Tried the C# example (had to add the dll reference) and all worked as expected. The language in C# with reflection is rather harsh even when compared with VBdotNet.

I believe I'm now at 0.1 level 😄

I have at this point some other questions if you don't mind to answer:

There are transactions which can lead to an export file (e.g. XLSX) and where the output is shown in a maximized window (e.g. EXCEL). Do we have any option from within SAP to save the file without displaying it? I can always find the instance and close it from outside SAP but it is sensible to ask the question and would make things easier;

I sometimes get an SAP GUI Security message box when I'm trying to save a file. When this happens (not every time) you always have the Allow/Deny option and a checkbox for "Remember My Decision". Running a scrip to suddenly have to click on the button isn't ideal. Is there a setting we can set to avoid these dialogues with questions to be asked? I went to security configuration and can only think this is the right place to look for it, but not sure of what should be changed for this. There is a "Default Action" with Ask/Allow/Deny, but don't wish to change anything without some kind of advice;

I usually start SAP from a window called SAP Logon 760 ("C:\Program Files (x86)\SAP\FrontEnd\SAPgui\saplogon.exe") and after I select from my Workspaces the one I need and click the Log On button. From here, a new windows is lunched (SAP Easy Access) where I can access all my transactions, record scripts, etc. What is the possibility for me to make the login process more automated? Yes I can easily start saplogon.exe but how can I, e.g. using VBdotNet, log on and open a SAP session? Is this possible? (I cannot run a scrip to view what happens in the process because this is only possible after I log on) And if yes, how do I know what details are required? I simply press a button and "I'm in".

I believe the above would be something you could support me with?

Please let me know.

Thank you

Kind regards,

Pedro

0 Kudos

Hi st.schnell

The code that you have provided here works the best with my use-case and it works as per the expectations. But I do have a doubt here, Can you let me know, how do we get the text value for a specific locator?
For e.g. I have a date input box, so I want to get the date from that input box.

I have tried this, but not sure if its the current way (or not), as this one is not working.

GetProperty(ID, "text", new object[1] { requiredLocator })

I got the answer by trial and error.I was using the wrong method.


Instead of this method

    GetProperty(this.ID, "text", new object[1] { requiredLocator })

We should use this method

    InvokeMethod(this.ID, "Text", new object[0])
where the *requiredLocator* and *ID*

can be set as

    this.ID = InvokeMethod(this.session, "findById", new object[1] { requiredLocator})

Answers (5)

Answers (5)

stefan_schnell
Active Contributor

ptuga

Hello Pedro,

you can find answers to suppress the security message here and here.

To automize more you can use this approach:

'-Begin-----------------------------------------------------------------

Imports System
Imports Microsoft.VisualBasic

Public Module SAPGUIScripting

  Sub Main()

    Dim SapGuiAuto As Object
    Dim app As Object
    Dim connection As Object
    Dim session As Object

    Try
      SapGuiAuto = CreateObject("Sapgui.ScriptingCtrl.1")
      app = SapGuiAuto.GetScriptingEngine
      app.HistoryEnabled = False
      connection = app.OpenConnection("C11", True)
      If connection.DisabledByServer = True Then
        Exit Sub
      End If
      session = connection.Children(0)
      If session.Info.IsLowSpeedConnection = True Then
        Exit Sub
      End If
    Catch ex As Exception
      Console.WriteLine(ex.Message)
      Exit Sub
    End Try

    '>Insert your SAP GUI Scripting code here<

    app.HistoryEnabled = True

  End Sub

End Module

'-End-------------------------------------------------------------------

But this approach is only available at x86 platform. With Sapgui.ScriptingCtrl.1 object and method OpenConnection it is possible to start direct the SAP session.

Do you have an example transaction which opens Excel instead of downloading?

Best regards
Stefan

ptuga
Explorer
0 Kudos

Hi Stefan,

Thank you for the feedback.

When you refer to "only available at x86 platform." I presume you mean Windows and that 64 bit Windows will not work with this code. Is this correct?

I've tried to run the code but when you reach to 'Connection = app.OpenConnection("C11", True)' it fails and the console shows a "SAP Logon connection entry not found" message even if SAP Logon 760 window is available. This might be cause by what you described on your comment?

We use several that allow an export to Excel, e.g. CS11, VA05 but I thought these could be very specific for the company rather than generic. In these cases, the Excel file is created and Excel is lunched to show the file. Just saving the file would be preferable.

Another point that I've been experiencing with the exports is the fact that the transaction code runs and finishes and the file has not yet been created/finalised. Because I'm running the SAP transaction/interfacing code on an external console app (VBdotNet), there is no way for my main application (Windows form in C#) to know exactly that the Excel file is ready. It seems that the SAP export does not wait until the Excel process is finished. It might run on a different thread, I suppose. The only way round this was for me to wait using a Thread.Sleep(ms) but if the export takes longer I'll run into trouble. My perception can also be wrong and something else is happening.

To finalise for today, I would like to ask, if it is possible to bring the SAP Easy Access window to the main screen with no other internal windows opened. Sometimes if a script fails, you are not starting from the initial main window screen and the scrip fails. Is there any workaround for this. You can press back (sendkey) several times and even if it works on most cases (not in all), seems very rudimentary.

I'll go through the security settings over the weekend and will let you know.

In the meanwhile, please feedback on the remaining topics.

Many thanks.

Kind regards,

Pedro

stefan_schnell
Active Contributor
0 Kudos

ptuga

Hello Pedro,

x86 platform means that you must compile your code with the x86 switch. It runs on 64-bit Windows, but it is an x86 application.

Instead of string C11 you must use your system description from the logon to start the correct connection. Please take a look at the SAP GUI Scripting help.

The FM XML_EXPORT_DIALOG contains an input parameter I_APPLICATION, if a related application can be detected it will be opened. Method GET_PC_APPLICATION from class CL_SALV_GUI_DATA_PUBLISHER do that, but I don't see a switch. I don't know a way around displaying the Excel file.

In my opinion you can check if the file exists and if you can add an additional file to it, Excel xlsx is a ZIP file. If this is possible it is probable that the download is complete.

Kill your SAP Logon and restart it, I know, this is radical but this step creates the desired conditions for you

Best regards
Stefan

ptuga
Explorer
0 Kudos

Hi Stefan,

Sorry for the long delay in my answer.

I'm an autodidact and sometimes can take a while until I find free time to look at none professional topics.

I'll try to compile an application in 32 bit to check what you mean. But for that I need the "system description" you mentioned.

The access to any help scripting seems to be only here:

file:///C:/Program%20Files%20(x86)/SAP/FrontEnd/sapgui/sapguihelp/EndUserHelp/EN/7ddb7c9c4a4c43219a65eee4ca8db001.html

But there is not a lot of info. Is there a link to show me the tips you mentioned?

The "system description" is likely to be a company/user specific thing, right?

Can I check this details after I login manually and look at a dialog?

Regarding the other topic, I need some extra investigation to reach a more accurate conclusion. In any case I appreciate your tips.

Now that I'm closer to a summer break I might have a bit more time for some reading.

You mentioned at the beginning of this ticket a dotNET Connector (NCo). For a starter, and for who would like to know a bit more, what do you recommend?

There are so many questions ... do we have the software in my machine? Where can I read about the topic and look for some examples?

You also mentioned "to automize via API, remote enabled function calls". What does this mean? Can I use VS and create VBdotNet apps to interact with SAP without the SAP GUI in between?

Can you provide me any details?

I believe I'm still at 0.1 level 😄 (I would like to step up a bit)

Thank you.

Kind regards,

Pedro

stefan_schnell
Active Contributor
0 Kudos

ptuga

Hello Pedro,
you can find more information about the system description in the SAP GUI Scripting help in the GuiApplication object, method OpenConnection. If you use method OpenConnectionByConnectionString, you can find all the parameters you need in your SAP Logon.

You can find all information you need about SAP dotNET Connector (NCo) in the support portal. The x86 version of NCo is part of the current SAP GUI for Windows installation. The NCo offers the possibility to communicate with the SAP backend system via remote enabled function calls (RFC). Yes, with NCo you can create VBdotNET apps to interact with SAP without the SAP GUI for Windows. You can find a few information in the Overview document.

Hope this answers your questions.

Best regards
Stefan

ptuga
Explorer
0 Kudos

Hi Stefan,

Sorry for the delay. And sorry if I don't understand your explanation.

When I said to leave the connection open, it means just that. Open the connection and leave it open for me to use as I please (using another app not within the same app). I can run a scrip once or twice but not within an automated process. When I need it.

The idea is if I need to run a scrip called from my external app, to make sure a connection is open for me to do that.

Creating the object but not deleting it after?

I'm not sure if this changes your perception on the question?

Also, I was able to get the connector files to start my new app. But where do I start?

Is there any basic/simple examples on how to run a transaction? Something as basic as if running code as if I'm running a script to get the same data?

Please let me know. I'm very keen to understand what's left for me to use.

Thanks.

Kind regards,

Pedro

stefan_schnell
Active Contributor
0 Kudos

Hello Pedro,

in my opinion it should be possible. Build a loop with a delay and in the loop you can check if a file exists. The file contains the SAP GUI Scirptings commands that you want to process synchronous and after that you jump back to the loop. After execution the file must be deleted. The session object must be passed as an argument. Now the next file can be processed.

Best regards
Stefan

ptuga
Explorer
0 Kudos

Hi Stefan,

In an ideal word yes, one language would be the logical thing to do, but as you showed me in one of your examples, using C# to do the scripting and the need to use the InvokeMethod/ SetProperty is not very "clean". Because I've been working is C# for a few years now, that is my rule, SAP interaction is the exception in my case. It also helps me to open to VBdotNet which I haven't used before.

For what is possible to me so far, it was worth the effort. I'm able to simulate the scripting which is a major achievement. Many thanks for that.

My question was just if you could open the connection and leave it open for the other process to use it. Can this be done? Is there any way how we can simply open a connection in SAP?

Please feedback.

Many thanks,

Pedro Cruz

ptuga
Explorer
0 Kudos

Hi Stefan,

Thank you for your answers.

I'll need time to investigate your comments.

The way I actually login, does not allow me to understand what is happening behind the login.

Using the method OpenConnectionByConnectionString and a string like "/H/iwdf8997.wdf.sap-ag.de/S/3200" is only good if I know what to use as the string. How will I know this?

I simply select the name of my system (e.g. Production ERP) and press Log On on the SAP Logon 760.

Then a new window starts and SAP Easy Access is shown confirming my login. I don't know any other way to lunch the SAP Easy Access.

Can you help?

Thank you.

Regarding the connector, this link points us to the place where we are able to download the software: https://support.sap.com/en/product/connectors/msnet.html

But it seems that not every one is able to download the applications.

The message:

You are not authorized to download this file Please make sure that your company has purchased this software product. If you have a valid license, but still cannot download this file, please report an incident under component XX-SER-SAPSMP-SWC. Incident ID: XYZ

What shall I do?

The company does have valid licences, but I'm not be using a valid email address.

What shall I do?

Please feedback.

Regards,

Pedro

stefan_schnell
Active Contributor
0 Kudos

ptuga

Hello Pedro,
you can find the SAP router string (/H/) and the connection number (/S/32 + instance number) of the connection string inside your SAP Logon.

To download the SAP NetWeaver RFC library contact you admin, he should have an S-user and be able to download the necessary files for you.

Best regards
Stefan

ptuga
Explorer
0 Kudos

Hi Stefan,

I have no idea about what you mean with "inside your SAP Logon.".

Under the SAP Logon 760 I have my workspaces and connections etc. which I need to select (one) before I press Log On.

I can select a workspace and all available connections are displayed at the right (e.g. productive system). If you right click on a connection, you can access properties and there are 3 tabs with Connection/Network/Code Page but nothing like what you have shown specifically.

I can find a SNC Name, Description, System ID, message server and the SAProuter which is blank and even Instance number as 00. Probably I'm not looking in the right place.

This connection type is set as "Group/Server Selection".

I cannot find any "SAProuter String" and I have no way to know unless you guide me to it.

If the connection is set to "Custom Application Server" then the text show will show, but this is not my case for the connection I use.

Any ideas?

Please feedback.

Thank you.

Kind regards,

Pedro

ptuga
Explorer
0 Kudos

Hi Stefan,

Should I start another question to discuss the connection topic?

I'm not sure how to progress from here since my connection type is set as "Group/Server Selection" and the "SAProuter String" does not seem to apply?

Could you please feedback?

Many thanks

Kind regards,

Pedro

stefan_schnell
Active Contributor
0 Kudos

ptuga

Hello Pedro,
sorry for my delayed reply.

To your questions:

  • Open in your SAP Logon the properties of the connection.

    In the properties you can find the Host /H/ string as SAP Router and the last two digits of the Service /S/32xx in the Instance Number.

  • You need an S-User with the permission to download files. Talk with your system administrator.

Best regards
Stefan

ptuga
Explorer
0 Kudos

Hi Stefan,

Delay is not a problem. Many thanks for your feedback.

My connections properties don't show the same dialog that you shown previously:

I guess that is because the "Connection Type" is set to "Group/Server Selection".

Once you change this to Custom Application Server" a very similar is displayed:

But no field is selected, and I don't wish to change this by obvious reasons.

I can find other connections (that I don't use) which are defined as "Custom Application Server" but all fields are filled except the "SAProuter String"! On this specific one the "Instance Number" is a 2 digits number, "SAProuter String" is empty.

Not really sure how to move from here?

Can you help?

Kind regards,

Pedro

ptuga
Explorer
0 Kudos

Hi Stefan,

Replacing "C11" in:

app.OpenConnection("C11", True)

with my connection "Description" did the trick!

Maybe some of the fields are empty, hence, not required and just the "Description" is fine.

Problem: When my app finishes the connection is closed immediately. Can I keep the connection open?

Please feeback.

Regards,

Pedro

stefan_schnell
Active Contributor
0 Kudos

Hello Pedro,

what do you want to do? If the automation via SAP GUI Scripting ends, it is not necessary to keep a connection open.

Best regards
Stefan

ptuga
Explorer
0 Kudos

Hi Stefan,

The way I'm doing things does not make it simple.

All my apps run in C# but for SAP interfacing I'm using VB dotNET because coding is much simpler.

So my main application (in C#) asks some requests to my slave application (VB dotNET).

Sometimes other requests might follow and I don't need to open a new connect everytime I make a new request.

Ideally, my slave app should check if one connection is open and execute the request from the main app and if not, should open a new connection but, leave it open once the code finishes for consequent requests to be executed also.

Does this make sense? Difficult to explain it in words.

Is this possible?

Regards,

Pedro

stefan_schnell
Active Contributor
0 Kudos

Hello Pedro,

from my perspective it makes no difference to automate SAP GUI via SAP GUI Scripting with C# or any other language. Sure is it possible to combine C# and VB.NET, but as you can see it can be more complex with the synchronization. In my opinion in this case one language approach would certainly be more beneficial.

Best regards
Stefan