Jump to content
DStraathof

Passing custom information from C# to AutoIT

Recommended Posts

Hi all,

I have an issue with a custom C# library & functions trying to use the result of these functions in AutoIT.

I have a custom library which can or will not be ported to AutoIT. It is however operational in C#. Therefor I started looking and searching for options to pass the result of a request to this library (using C#) to AutoIT.

I found LarsJ's examples of a DotNet AutoIt library, which could be helpful in using the necessary libraries and C# code in AutoIT.

 

The custom library will securely (using all types of verification and security levels) select user credentials for a given customerID.

The following C# code will actually do that (sorry, won't be able to post the library DLLs itself)

using System;
using SecureLib;

namespace CustomerDetails
{
    class User
    {
        static void Main()
        {
            var userdetails = CMDB("23680"); // get the userdetails for customerID 23680
            
            foreach (var item in userdetails)
            {
                Console.WriteLine(item);
            }
            Console.ReadLine();
        }

        static public string[,] CMDB(string cmp)
        {
            var y = new SecLibrary.Control();
            var testInfo = y.FetchTestInformation(ref cmp);
            string[,] SelectedUser = new string[,] {
            { "Username", testInfo.Username.ToString() },
            { "Password", testInfo.Password.ToString() },
            { "WebURL", testInfo.WebURL.ToString() }
            };
            return SelectedUser;
        }
    }
}

Next, I tried to grab the given information from the CMDB static stringarray in AutoIT usoing the following:

#include "..\..\..\..\Includes\DotNetAll.au3"

Opt( "MustDeclareVars", 1 )

Example()

Func Example()
    Local $oNetCode = DotNet_LoadCScode( FileRead( "Program.cs" ), "System.dll | C:\References\Secure Library\SecLibrary.dll | C:\References\Secure Library\Security.ServiceBus.Helpers.dll" )
    Local $oUserDetails = DotNet_CreateObject( $oNetCode, "CustomerDetails" )
    Local $aVariants = $oUserDetails.CMDB('23680')
    _ArrayDisplay( $aVariants )
EndFunc

When running the C# code it will give me the user details for the given customerID, but when running the AutoIT code it will error on:

The requested action with this object has failed.:
Local $aVariants = $oUserDetails.CMDB('23680')
Local $aVariants = $oUserDetails^ ERROR

I surely hope that one of the "Walking C# AutoIT knowledge base guru's" 😉 can help me out here...

Thanks in advance.

 

 

 

Share this post


Link to post
Share on other sites

DotNet_CreateObject takes class as second parameter and if you use a namespace it must be "namespace.class".

The method called in the AutoIt code must be defined relatively simple. In CMDB, the static keyword causes problems. The general solution is to add a new simple method to handle the communication between AutoIt and the C# code. Here getCMDB.

I've tested this code:

using System;

namespace CustomerDetails
{
  class User
  {
    public string[,] getCMDB(string cmp)
    {
      return CMDB(cmp);
    }
    
    static public string[,] CMDB(string cmp)
    {
      string[,] SelectedUser = new string[,] {
      { "Username", "Username" },
      { "Password", "Password" },
      { "WebURL", "WebURL" }
      };
      return SelectedUser;
    }
  }
}
#include "DotNetAll.au3"
#include <Array.au3>

Opt( "MustDeclareVars", 1 )

Example()

Func Example()
  Local $oNetCode = DotNet_LoadCScode( FileRead( "tst00.cs" ), "System.dll" )
  Local $oUserDetails = DotNet_CreateObject( $oNetCode, "CustomerDetails.User" )
  Local $aVariants = $oUserDetails.getCMDB('23680')
  _ArrayDisplay( $aVariants )
EndFunc

 

Note that arrays are different in AutoIt and C# code as rows and columns are swapped. You may want to use this array in the C# code:

{ "Username", "Password", "WebURL" },
{ "Username", "Password", "WebURL" }

 

Share this post


Link to post
Share on other sites

Hi LarsJ,

Thank you for a clear reply. Using the extra getCMDB function works for returning the string array.

The issue I'm currently facing is the usage of the SecureLib library with the 2 extra DLLs, and this function call in the C# code:

            var y = new SecLibrary.Control();
            var testInfo = y.FetchTestInformation(ref cmp);

Will try myself using another personally created DLL will face the same problem.

Keep you posted!

Share this post


Link to post
Share on other sites

I have tested with a more basic custom DLL, but I can't get it to work properly. It seems that loading the custom DLL works, but referring from the C# script to this, by AutoIT loaded, DLL doesn't seems to work:

Here's my class DLL:

using System;

namespace SelectUser
{
    public class Greetings
    {
        public static string Hello(string name)
        {
            return $"Greetings {name}";
        }
    }
}

This is the Program.cs, using/including the SelectUser.dll class created using Visual Studio:

using System;
using SelectUser;

namespace CustomerDetails
{
  class User
  {
    public string getCMDB(string cmp)
    {
      return Greetings.Hello(cmp);
    }
  }
}

This is the AutoIT script:

#include "..\..\..\..\Includes\DotNetAll.au3"
#include <Array.au3>

Opt( "MustDeclareVars", 1 )

Example()

Func Example()
  Local $oNetCode = DotNet_LoadCScode( FileRead( "Program.cs" ), "System.dll | C:\References\SelectUser.dll" )
  Local $oUserDetails = DotNet_CreateObject( $oNetCode, "CustomerDetails.User" )
  Local $sVariants = $oUserDetails.getCMDB('23680')
  ConsoleWrite( $sVariants )
EndFunc

Could it be the nesting namespacing (form the .cs and the .dll and functions in C# that are blocking?

The expected output should be: "Greetings 23680"

Thanks for the help.

 

Program.cs ToAutoItCS.au3 Class1.cs

Share this post


Link to post
Share on other sites

When running C# code through AutoIt, there are probably some restrictions over what you can do in pure C# code. In the examples with DotNet_LoadCScode(), only assemblies registered in the GAC are used. In contrast, assemblies not registered in the GAC are loaded with DotNet_LoadAssembly().

In a very short test, I also couldn't make your code work. But I've made this code work:

using System;

namespace SelectUser
{
  public class Greetings
  {
    public static string Hello(string name)
    {
      return "Greetings " + name;
    }
  }
}

namespace CustomerDetails
{
  class User
  {
    public string getCMDB(string cmp)
    {
      return SelectUser.Greetings.Hello(cmp);
    }
  }
}
#include "DotNetAll.au3"

DotNet_LoadCScode( FileRead( "tst02.cs" ), "System.dll", 0, "tst02.dll" )
#include "DotNetAll.au3"

Opt( "MustDeclareVars", 1 )

Example()

Func Example()
  Local $oComErrFunc = ObjEvent( "AutoIt.Error", "ComErrFunc" )
  Local $oNetCode = DotNet_LoadAssembly( "tst02.dll" )
  Local $oUserDetails = DotNet_CreateObject( $oNetCode, "CustomerDetails.User" )
  Local $sVariants = $oUserDetails.getCMDB('23680')
  ConsoleWrite( $sVariants )
EndFunc

In Visual Studio, if you create a single assembly dll and load it with DotNet_LoadAssembly(), it might be the easiest.

Run the AutoIt code in SciTE with F5 so you can see error messages in the console. In the code above I've added a COM error handler.

Share this post


Link to post
Share on other sites

Hi LarsJ,

Thanks for the reply. I will test it this tomorrow.

The issue why I need to include extra external DLLs is, that I can't include the functions from the Security DLLs in my own coded DLL.
The external DLLs being:

C:\References\Secure Library\SecLibrary.dll | C:\References\Secure Library\Security.ServiceBus.Helpers.dll" 

I need to find a way to do this, but I'll try your example code and let you know 🙂

Thanks again for thinking this through.

Share this post


Link to post
Share on other sites

As I was afraid.... I need both external DLLs to be loaded into the AutoIT script.

I cannot use the 'concatenate' option as with the DotNet_LoadCScode() function to load both DLLs in the same AutoIT object:

Local $oNetCode = DotNet_LoadAssembly( "C:\References\Secure Library\SecLibrary.dll | C:\References\Secure Library\Security.ServiceBus.Helpers.dll" )

It returns an error:

ToAutoItCS.au3(1136): ==> COM Error intercepted!
    Err.number is:      0x000000A9
    Err.windescription: Variable must be of type 'Object'.  Err.description is:     
    Err.source is:      
    Err.helpfile is:    
    Err.helpcontext is:     
    Err.lastdllerror is:    0
    Err.scriptline is:  1136
    Err.retcode is:     0x00000000

Is it possible to have 2 objects, and assign the compiled functions both in one AutoIT DotNet_CreateObject (hence the { } ), i.e.:

#include "Includes\DotNetAll.au3"
#include <Array.au3>

Opt( "MustDeclareVars", 1 )

Example()

Func Example()
  Local $oComErrFunc = ObjEvent( "AutoIt.Error", "ComErrFunc" )
  Local $oNetCodeLibrary = DotNet_LoadAssembly( "C:\References\Secure Library\SecLibrary.dll" )
  Local $oNetCodeServiceBus = DotNet_LoadAssembly( "C:\References\Secure Library\Security.ServiceBus.Helpers.dll" )  
  Local $oSecureControl = DotNet_CreateObject( {$oNetCodeLibrary,$oNetCodeServiceBus}, "SecLibrary.Control" )
  Local $oUserDetails = $oSecureControl.FetchTestInformation('23680')
  ConsoleWrite( $oUserDetails.Username )
EndFunc

Thanks again for thinking with me 🙂

 

Share this post


Link to post
Share on other sites

I don't know. What did you see when you ran the code? I'll take a closer look at the problem with third party assembly dlls. But I need time. Until there is nothing else to do but separate C# and AutoIt code. If you need the results from C# in AutoIt, you'll have to pass them through a file or similar.

Share this post


Link to post
Share on other sites

Hi LarsJ,

Because both DLLs won't be loaded, the error states:

Unable to parse line.: 
Local $oSecureControl = DotNet_CreateObject( {$oNetCodeLibrary,$oNetCodeServiceBus}, "SecLibrary.Control" ) 
Local $oSecurecontrol = DotNet_CreateObject( ^ ERROR

So basically no clear error about this.

I myself was also thinking about exchanging data between C# and AutoIt through a file. I'll try and see what will happen there.

Thanks for looking into it.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...