One Size Fits All

In this post I will describe a few perspectives about integration aspects via the using of libraries on RPA platforms. It could be possible that the following combinations of programming languages and platforms are controversial, but it shows us the variety of possibilities.

Command Line Interface

Many tools offer a command line interface (CLI) to control it. RPA platforms offers in standard an execute activity to run this kind of application. But it is more or less difficult to handle the process with its complete range, which is offer by the operating system respectively the dotNET framework. It seems to be good to build an own CLI handler library. On this way we can use all the possibilities we need. To realize this, we call the method Process.Start, from System.Diagnostic namespace, with the ProcessStartInfo class. With the properties of this class, we can make an adjustment according to our wishes, e.g. CreateNoWindow or RedirectStandardOutput.

Integration Aspect

There is already a variety of existing automation solutions in the IT landscape. For a fast implementation, the question of how these can be integrated into an RPA platform arises from time to time. It is not unusual to continue the using of existing consolidated automation approaches in the RPA environment. Not every existing solution must necessarily be implemented in RPA, but can also be integrated in RPA. We consider here the integration of AutoIt CLI, as an example. It is a powerful scripting language designed for automating the Windows GUI and general scripting. In business there are several solutions which bases on AutoIt.

Create Library

With the above information it is now very easy to encode a dotNET library in C#.

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

using System;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using System.Reflection;
using System.Diagnostics;
using System.Threading.Tasks;

[assembly:AssemblyVersionAttribute("1.0.0.0")]
[assembly:AssemblyFileVersionAttribute("1.0.0.0")]
[assembly:AssemblyCopyrightAttribute("Stefan Schnell")]
[assembly:AssemblyCompanyAttribute("Stefan Schnell")]
[assembly:AssemblyProductAttribute("AutoIt for dotNET")]

public class AutoIt4dotNET {

  //-Run----------------------------------------------------------------
  //-
  //- Executes the AutoIt file and deliver, in case of error,
  //- the error text, otherwise the console output of AutoIt.
  //-
  //- Arguments
  //- FilePath    = Path and name of the AutoIt script
  //-               which should be executed
  //- x64         = Signal whether the x64 or the x86 version
  //-               should be executed
  //- AutoItPath  = Path to the AutoIt executable, standard is
  //-               C:\Program Files (x86)\AutoIt3\
  //- OutputDebug = Signal to send the output additional to the
  //-               debug output of the local system
  //-
  //--------------------------------------------------------------------
  public string Run(
    string FilePath,
    bool x64,
    string AutoItPath,
    bool OutputDebug
  ) {

    if(FilePath == "") {
      return "Error: FilePath missing";
    }

    string AutoItExe = string.Empty;
    if(x64 == true) {
      AutoItExe = @"AutoIt3_x64.exe";
    } else {
      AutoItExe = @"AutoIt3.exe";
    }

    if(AutoItPath != "") {
      AutoItExe = AutoItPath + @"\" + AutoItExe;
    }

    ProcessStartInfo start = new ProcessStartInfo();

    start.FileName = @AutoItExe;
    if(OutputDebug == true) {
      start.Arguments = @"/ErrorStdOut /AutoIt3OutputDebug " + @FilePath;
    } else {
      start.Arguments = @"/ErrorStdOut " + @FilePath;
    }
    start.CreateNoWindow = true;
    start.UseShellExecute = false;
    start.RedirectStandardOutput = true;
    start.RedirectStandardError = true;

    Process process;
    try {
      process = Process.Start(start);
      process.WaitForExit();
    } catch(Exception ex) {
      return ex.Message;
    }

    string Result = string.Empty;
    if(process.StandardError.ReadToEnd() != "") {
      Result = process.StandardError.ReadToEnd();
    } else {
      Result = process.StandardOutput.ReadToEnd();
    }

    return Result;

  }

}

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

One class with one method is enough in our case. The Run method checks the input parameter first, then it filles the properties of the ProcessStartInfo class, e.g. like filename, arguments etc. Then it starts the process, waits for end of execution and delivers the output.

AutoIt Test Script

To check the library we need an AutoIt test script. Here an easy one which opens a message box and delivers a text depending on the executing architecture.

;-Begin-----------------------------------------------------------------

If @AutoItX64 = 1 Then
  MsgBox(0, "AutoIt", "Version " & @AutoItVersion & " x64")
  ConsoleWrite("Hello World from AutoIt Version " & @AutoItVersion & " x64")
Else
  MsgBox(0, "AutoIt", "Version " & @AutoItVersion & " x86")
  ConsoleWrite("Hello World from AutoIt Version " & @AutoItVersion & " x86")
EndIf

;-End-------------------------------------------------------------------

Using of this Library with PowerShell

We perform the first test of the library with PowerShell.

#-Begin-----------------------------------------------------------------

#-Sub Main--------------------------------------------------------------
Function Main {

  Add-Type -Path "$($PSScriptRoot)\AutoIt4dotNET.dll";    

  [AutoIt4dotNET]$AutoIt = [AutoIt4dotNET]::new();

  $Result = $AutoIt.Run("$($PSScriptRoot)\AutoIt4dotNET.au3", `
    $true, "C:\Program Files (x86)\AutoIt3", $false);

  Write-Host $Result;

  $Result = $AutoIt.Run("$($PSScriptRoot)\AutoIt4dotNET.au3", `
    $false, "C:\Program Files (x86)\AutoIt3", $true);

  Write-Host $Result;

}

#-Main------------------------------------------------------------------
Main;

#-End-------------------------------------------------------------------

All works well and as expected. x64 and x86 call as well as the output in the debug monitor.

Using of this Library

With UiPath it is necessary to pack the library with nuget first.

Here the nuget spec I use.

<?xml version="1.0"?>
<package >
  <metadata>
    <id>AutoIt4dotNET</id>
    <version>1.0.0</version>
    <authors>Stefan Schnell</authors>
    <owners>Stefan Schnell</owners>
    <licenseUrl>https://opensource.org/licenses/MIT</licenseUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>dotNET Library with CLI for AutoIt, executes AutoIt.exe</description>
    <releaseNotes>Intial Release.</releaseNotes>
    <copyright>Copyright Stefan Schnell</copyright>
    <language>en-US</language>
    <tags>autoit scripting script automation library dotnet interface cli</tags>
  </metadata>
  <files>
    <file src="AutoIt4dotNET.dll" target="lib\net40"></file>
  </files>
</package>

Now we can add the library via managed packages.

image

And we can use the same code.

image

Here the workflow …

… with the result.

image

All works well an expected.

Conclusion

This approach shows us a few things:

  • The integration of existing software via CLI and a special library, which encapsulate the call with all possibilities, is very easy to realize.
  • The integration of existing automation approaches is just as simple in this way.
  • It is possible to use one library for different RPA platforms. They just need to be packaged slightly differently, as shown in this example.
  • By cleverly packaging the code activity, easy use and reuse can be realized.

I hope this excursion across four programming languages and two RPA platforms has opened some integration perspectives.

11 Likes

As a tiny addendum here a NuGet package to use AutoIt seamlessly in UiPath, without an additional installation of AutoIt. This package contains the x86 and x64 version of AutoIt and the include directory. It is also now possible to pass parameters to the AutoIt script.

Here the package:

AutoIt.Activities.2.0.0.nupkg (1.7 MB)

Here an AutoIt test script:

;-Begin-----------------------------------------------------------------

#Include <MsgBoxConstants.au3>

Local $Name = ""
Local $Message = ""

If $CmdLine[0] > 0 Then
  $Name = $CmdLine[1]
  $Message = $CmdLine[2]
EndIf

If @AutoItX64 = 1 Then

  MsgBox($MB_OK + $MB_ICONINFORMATION, "AutoIt", "Version " & _
    @AutoItVersion & " x64")
  If $Name = "" Then
    ConsoleWrite("Hello World from AutoIt Version " & _
      @AutoItVersion & " x64")
  Else
    ConsoleWrite("Hello " & $Name & " from AutoIt Version " & _
      @AutoItVersion & " x64")
  EndIf

Else

  MsgBox($MB_OK + $MB_ICONINFORMATION, "AutoIt", "Version " & _
    @AutoItVersion & " x86")
  If $Message = "" Then
    ConsoleWrite("Hello World from AutoIt Version " & _
      @AutoItVersion & " x86")
  Else
    ConsoleWrite($Message & @AutoItVersion & " x86")
  EndIf

EndIf

;-End-------------------------------------------------------------------

Here an example sequence:


image

And here the result:

image

With this approach is it possible to use AutoIt with its full range of functions in the context of UiPath, without any additional installation. This simplifies the distribution to the bots. The possibility which I described here: How to use Automation Language AutoIt in Combination with UiPath uses AutoItX, which has a reduced command set.

Here my example project: AutoIt.zip (26.7 KB)

Here the interface description:

//-Run------------------------------------------------------------------
//-
//- Executes the AutoIt file and deliver, in case of error,
//- the error text, otherwise the console output of AutoIt.
//-
//- Arguments
//- FilePath    = Path and name of the AutoIt script
//-               which should be executed
//- Arguments   = Command line parameters, optional,
//                default is empty string
//- TimeOut     = Wait milliseconds for the process to exit,
//-               optional, default is infinite (-1)
//- x64         = Signal whether the x64 or the x86 version
//-               should be executed, optional, default is true
//- AutoItPath  = Path to the AutoIt executable, if AutoIt is
//-               local available, with standard installation it is
//-               C:\Program Files (x86)\AutoIt3, optional,
//-               default is empty string
//-               Hint: With the NuGet package it is not necessary to
//-               set this path, pass an empty string if necessary
//- OutputDebug = Signal to send the output additional to the
//-               debug output of the local system, optional,
//-               default is false
//-
//----------------------------------------------------------------------

Enjoy the possibility of the UiPath/AutoIt combination. :grinning:

1 Like

Here from the NuGet package, which is available in the post above, a few impressions.

image

image

The use is equal to the AutoIt4dotNET approach.

Enjoy the possibility of the UiPath/AutoIt combination. :grinning:

4 Likes

Last but not least I tried the same procedure as in my post How to use the Automation Language AutoIt in Combination with UiPath.

Here the video

Great, all works as expected :smiley:

2 Likes