Tip: How to Load Assembly DLLs Dynamically
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
06-01-21 04:28 PM
in my opinion dynamic loading of dotNET assembly DLLs at the runtime a necessity. Therefore here a first approach how this possibility can be realized.
At first I developed a tiny library, which I packed in a NuGet.
//-Begin----------------------------------------------------------------
using System;
namespace test {
public class nuget {
public string mtest(string Input = "") {
if(String.IsNullOrEmpty(Input)) {
return "Hello World";
} else {
return "Hello " + Input;
}
}
}
}
//-End------------------------------------------------------------------
In the next step I installed this NuGet package at the target system in the UserProfile directory.
nuget.exe Install TestNuget -Source "%cd%" -OutputDirectory "%USERPROFILE%\.nuget"
And with a Code Stage I call the method of this library dynamically, independently from the customizing in the Code Options.
//-Begin----------------------------------------------------------------
Result = string.Empty;
ErrRet = string.Empty;
string UserDir = Environment.GetEnvironmentVariable("UserProfile");
string DLLPath = UserDir + "\\.nuget\\TestNuget.1.0.0\\lib\\net40";
try {
//-Loads assembly-----------------------------------------------------
Assembly TestNugetDLL = Assembly.LoadFile(DLLPath + "\\TestNuget.dll");
//-Gets the class type------------------------------------------------
Type TestNugetClass = TestNugetDLL.GetType("test.nuget");
if(TestNugetClass == null) {
return;
}
//-Gets the method----------------------------------------------------
MethodInfo mtest = TestNugetClass.GetMethod("mtest");
//-Creates instance of the class--------------------------------------
object TestNugetObj = Activator.CreateInstance(TestNugetClass);
//-Call method without parameter--------------------------------------
var oResult = mtest.Invoke(TestNugetObj, new object[] { null });
Result = oResult.ToString();
Result += Environment.NewLine;
//-Call method with parameter-----------------------------------------
oResult = mtest.Invoke(TestNugetObj, new object[] { "Stefan" });
Result += oResult.ToString();
} catch(Exception ex) {
ErrRet = ex.Message;
}
//-End------------------------------------------------------------------
Only the namespace System.Reflection must be included.
Yes, including the library and calling the methods is "a bit cumbersome". But this approach offers a great possibility, to call methods of an assembly which are not in the program directory of BP. This separation simplifies especially the deployment of libraries.
Enjoy it.
Best regards
Stefan
------------------------------
Stefan Schnell
Senior Systems Engineer at BWI GmbH
------------------------------
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
06-01-21 08:41 PM
Thanks for you contribution.
Regards
------------------------------
Jhogel Ponne
Senior RPA
Ernst & Young
America/Panama
------------------------------
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
07-01-21 06:14 AM
to verify my approach I tried to use the integration of AutoIt scripting language, I have described the basic approach here in the context of different RPA platforms.
I was particularly interested in using the existing NuGet package.
I installed the existing NuGet package in the user directory.
In the next step I build an object to use the AutoIt library.
Here the Code Stage:
//-Begin----------------------------------------------------------------
//-Initialization of output variables-----------------------------------
Result = string.Empty;
ErrorMessage = string.Empty;
//-Check if file exists-------------------------------------------------
if(!File.Exists(AutoItFileName)) {
ErrorMessage = "File not found";
Console.WriteLine(ErrorMessage);
return;
}
string UserDir = Environment.GetEnvironmentVariable("UserProfile");
string DLLPath = UserDir + "\\.nuget\\AutoIt4dotNET.1.0.0\\lib\\net40";
try {
//-Loads AutoIt assembly----------------------------------------------
Assembly AutoItDLL = Assembly.LoadFile(DLLPath + "\\AutoIt4dotNET.dll");
//-Gets the class type------------------------------------------------
Type AutoItClass = AutoItDLL.GetType("AutoIt4dotNET");
if(AutoItClass == null) {
return;
}
//-Gets the method----------------------------------------------------
MethodInfo Run = AutoItClass.GetMethod("Run");
//-Creates instance of the class--------------------------------------
object AutoIt = Activator.CreateInstance(AutoItClass);
//-Call method--------------------------------------------------------
var oResult = Run.Invoke(AutoIt, new object[] {
AutoItFileName,
Arguments,
Convert.ToInt32(TimeOut),
x64,
"", //-Path to AutoIt if local available, not necessary here
OutputDebug
});
Result = oResult.ToString();
} catch(Exception ex) {
ErrorMessage = ex.Message;
}
//-End------------------------------------------------------------------
It works as expected.
This approach shows us how to use libraries of NuGet packages with BP, with the advantage that the libraries no longer have to be stored in the BP program directory. In addition, we also see how AutoIt can be seamlessly integrated with BP via its CLI.
Enjoy it.
Best regards
Stefan
------------------------------
Stefan Schnell
Senior Systems Engineer at BWI GmbH
------------------------------
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
07-01-21 04:59 PM
excellent piece of work! I like your posts very much! Thanks for your contributions here!
However, I have one question - when you use this approach (I haven't had time to play with it that's why I am asking) - you are not getting syntax errors from Code Stage? BP is able to understand references thanks to System.Reflection or....?
Regards,
------------------------------
Zdeněk Kabátek
Head of Professional Services
NEOOPS
http://www.neoops.com/
Europe/Prague
------------------------------
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
08-01-21 05:51 AM
thank you very much for your reply.
I got no syntax errors, all works well and as expected.
As attachment a tiny video.
Best regards
Stefan
------------------------------
Stefan Schnell
Senior Systems Engineer at BWI GmbH
------------------------------
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
09-01-21 05:23 PM
with the knowledge of how to use dynamic data type is it possible to simplify the code and make it better understandable.
The call method section now consists of only one line.
Enjoy it.
Best regards
Stefan
//-Begin----------------------------------------------------------------
//-Initialization of output variables-----------------------------------
Result = string.Empty;
ErrorMessage = string.Empty;
//-Check if file exists-------------------------------------------------
if(!File.Exists(AutoItFileName)) {
ErrorMessage = "File not found";
Console.WriteLine(ErrorMessage);
return;
}
string UserDir = Environment.GetEnvironmentVariable("UserProfile");
string DLLPath = UserDir + "\\.nuget\\AutoIt4dotNET.1.0.0\\lib\\net40";
try {
//-Loads AutoIt assembly----------------------------------------------
Assembly AutoItDLL = Assembly.LoadFile(DLLPath + "\\AutoIt4dotNET.dll");
//-Gets the class type------------------------------------------------
Type AutoItClass = AutoItDLL.GetType("AutoIt4dotNET");
if(AutoItClass == null) {
return;
}
//-Gets the method----------------------------------------------------
MethodInfo Run = AutoItClass.GetMethod("Run");
//-Creates instance of the class--------------------------------------
dynamic AutoIt = Activator.CreateInstance(AutoItClass);
//-Call method--------------------------------------------------------
Result = AutoIt.Run(
AutoItFileName,
Arguments,
Convert.ToInt32(TimeOut),
x64,
"", //-Path to AutoIt if local available, not necessary here
OutputDebug
);
} catch(Exception ex) {
ErrorMessage = ex.Message;
}
//-End------------------------------------------------------------------
------------------------------
Stefan Schnell
Senior Systems Engineer at BWI GmbH
------------------------------
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
11-01-21 11:39 AM
It works if you just have a few methods in dll, but problem is that you dont have namespace anymore and missing all the enums etc.
------------------------------
Andrey Kudinov
Project Manager
MobileTelesystems PJSC
Europe/Moscow
------------------------------
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
11-01-21 07:07 PM
Hello Andrey,
thank you very much for this interesting hint.
Best regards
Stefan
------------------------------
Stefan Schnell
Senior Systems Engineer at BWI GmbH
------------------------------
