Posts: 1,031
Threads: 246
Joined: Jul 2022
06-20-2023, 05:29 AM
(This post was last modified: 06-20-2023, 05:35 AM by Davider.)
Very good sharing.
In QM, using the CsScript class can only execute C#5 version of code. Can you create a function( CallLa) to execute C#6 or higher code in LA? For example C#8 ,thank you.
I am currently confused about how to implement this function: need to create a temporary LA script file? Then use the HTTP service above to call the function?
Should calling functions using HTTP services be the fastest compared to other methods while LA is running?
Macro Macro9
str cs5=
;using System;
;public class Test
;{
;,public static string Main(string p)
;,{
;,,string r = String.Format("hello {0}", p);
;,,Console.WriteLine(r);
;,,return r;
;,}
;}
CsScript x.AddCode(cs5)
str p="Lisa"
str R=x.Call("Main" p)
out R
;__________________________________________________________________Todo:
str cs8=
;using System;
;public class Test
;{
;,public static string Main(string name)
;,{
;,,string r=$"hello {name}";
;,,Console.WriteLine(r);
;,,return r;
;,}
;}
;Todo: Call the Main function in the cs8 code in LA through http
;CallLa(cs8 "Main" "Lisa")
Posts: 12,073
Threads: 140
Joined: Dec 2002
It is in post #6 in this thread.
Posts: 1,031
Threads: 246
Joined: Jul 2022
need to create a function in #5Code to handle cs8 code? I'm not very familiar with C # code yet
Posts: 12,073
Threads: 140
Joined: Dec 2002
06-20-2023, 05:58 AM
(This post was last modified: 06-20-2023, 05:59 AM by Gintaras.)
Don't need #5. Only #6.
Create C# functions in #1 code.
Posts: 1,031
Threads: 246
Joined: Jul 2022
06-20-2023, 09:47 AM
(This post was last modified: 06-20-2023, 10:00 AM by Davider.)
Currently, I using the following method, but it is slow and takes 4 seconds (LinqPad7 is in the open state.)
I need to execute quickly enough!
Macro Macro10
str cs8=
;using System;
;public class Test
;{
;,public static string Main(string name)
;,{
;,,string r=$"hello {name}";
;,,Console.WriteLine(r);
;,,return r;
;,}
;}
cs8.setfile("$desktop$\LP7\cs8.linq")
str cl=
;lprun7 -lang=P cs8.linq "Lisa"
RunConsole2 cl _s "$desktop$\LP7"
out _s
The above solution conveys a relatively single data type, and using LA should be faster and more convenient, Can someone provide an example? Thank you
Using the CS-Script class library, combined with the following code, may be more flexible, but it requires referencing a lot of dlls...
https://github.com/oleg-shilo/cs-script....samples.cs
Posts: 12,073
Threads: 140
Joined: Dec 2002
In QM create function LaHttpCall from the above post.
Move C# function Main from QM macro to C# server class Functions. Rename, for example to Main2.
Call it in QM:
_s=LaHttpCall("Main2" "name=Lisa")
Not tested.
Posts: 1,031
Threads: 246
Joined: Jul 2022
successfully executed, thanks for your help!
There may be an error in my expression above. I mean is that the C# code needs to be executed is generated in QM, and there is no such code in LA, because these C# codes are written in a higher version of the C# language, so they need to be executed in LA or LP
Posts: 12,073
Threads: 140
Joined: Dec 2002
06-20-2023, 02:52 PM
(This post was last modified: 06-20-2023, 02:53 PM by Gintaras.)
What is the reason to generate C# code in QM? When/where it can be useful?
Posts: 1,031
Threads: 246
Joined: Jul 2022
06-20-2023, 03:15 PM
(This post was last modified: 06-20-2023, 03:19 PM by Davider.)
#8 -> Macro9
The code in variable cs8 cannot be executed using Call in QM(Because it using the syntax of C#8.0)
Usage scenario:
Sometimes, I find some C#8|9|10 syntax function code, but I want to use it in QM
Posts: 12,073
Threads: 140
Joined: Dec 2002
06-20-2023, 03:33 PM
(This post was last modified: 06-20-2023, 03:37 PM by Gintaras.)
But why to store C# code in a QM macro? You can store it in LA. I want to know some reasons why people want to pass C# code to LA to compile and execute.
In LA Cookbook there is recipe "Use C# compiler at run time". Using that code you can create a function that compiles and executes code passed from QM or elsewhere. Will need to install the NuGet package (the easy way) or add references to the LA compiler dlls; they are in LA subfolder Roslyn.
The first call will take 1 or several seconds depending on computer speed. Then about 100 ms.
When C# code is in LA, the speed is about 1 ms. First time a little slower.
Posts: 1,031
Threads: 246
Joined: Jul 2022
06-20-2023, 03:44 PM
(This post was last modified: 06-20-2023, 04:13 PM by Davider.)
Quote:I want to know some reasons why people want to pass C# code to LA to compile and execute
Previously, I had some PowerShell automation scripts that were difficult to implement using PowerShell. Due to the availability of existing C# code, I edited the C# code using LINQPad and then called and executed it using the command line method below.
lprun7 -lang=P cs8.linq "Lisa"
until I met QM. Now I use QM exclusively to achieve my goals.
For my work, using QM is enough, but C# has many free libraries and functions, which can be a supplement to QM.
Quote:Use C# compiler at run time
It seems a bit complicated. I have a simple unverified idea:
In QM, send a window message to LA to append the C# code to the end of the HTTP server script.
Then execute the command in QM, Is this possible?
LaHttpCall("Main2" "name=Lisa")
Macro Macro10
_s=
;public static string Main2(string name) {
;,string r = $"hello {name}";
;,Console.WriteLine(r);
;,return r;
;}
;Todo: send a window message to LA to append the C# code to the end of the HTTP server script
;SendMessage
_s=LaHttpCall("Main2" "name=Lisa"); out _s
Posts: 1,031
Threads: 246
Joined: Jul 2022
The following example code cannot be executed
/*/ nuget Roslyn\Microsoft.CodeAnalysis.CSharp; /*/
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis;
using System.Runtime.Loader;
using System.Reflection;
string code = """
using System;
using Au;
foreach (var v in args) print.it(v);
dialog.show("test");
""";
var c = CsScript.Compile(code);
if (c == null) return;
//print.redirectConsoleOutput = true; //need this if the script contains Console.WriteLine and the caller app isn't console
c.Run("command", "line", "arguments");
Posts: 12,073
Threads: 140
Joined: Dec 2002
06-21-2023, 03:34 AM
(This post was last modified: 06-21-2023, 03:36 AM by Gintaras.)
Scroll down, you will find class CsScript, add it to your script.
Quote:In QM, send a window message to LA to append the C# code to the end of the HTTP server script.
Bad idea.
Posts: 1,031
Threads: 246
Joined: Jul 2022
Thanks for your reminder,
now prompts the following error
FAILED TO COMPILE
error CS0009: Metadata file 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\6.0.18\System.IO.Compression.ZipFile.dll' could not be opened -- PE image doesn't contain managed metadata.
error CS0009: Metadata file 'C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\6.0.18\System.Windows.Forms.Design.Editors.dll' could not be opened -- PE image doesn't contain managed metadata.
Posts: 12,073
Threads: 140
Joined: Dec 2002
Don't know, on my PC no error.
Posts: 1,031
Threads: 246
Joined: Jul 2022
Strange, I successfully tested on another Win10 system,
Posts: 1,031
Threads: 246
Joined: Jul 2022
06-21-2023, 10:38 AM
(This post was last modified: 06-21-2023, 10:42 AM by Davider.)
After testing, Method #13 is the fastest, and Method #19 is slow.
I have a question: If the code for my function Main2 is lengthy, for easy maintenance and modification in the future, can I write it in a separate script file(Separating it from the HTTP server script.) and call it in QM using the below code?
s=LaHttpCall("Main2", "name=Lisa")
Posts: 12,073
Threads: 140
Joined: Dec 2002
In LA create new folder, name "@HttpServer" or any name with @ prefix.
Move script "HTTP server" into that folder.
Create new class file in that folder, for example named "HttpServerFunctions". Cut entire Functions class from script "HTTP server", and paste in the new file, replacing its default code.
Script "HTTP server" must be the first file in that folder.
In the future you can create more class files in that folder, and add more functions there. Make the Functions class partial and use in each file.
Posts: 1,031
Threads: 246
Joined: Jul 2022
06-21-2023, 12:36 PM
(This post was last modified: 06-21-2023, 12:43 PM by Davider.)
thank you so much, I have learned a lot about LA!!!
I put the code into the class file " HSFun_Temp" It runs well.
But, I would like to write the code in the QM script for future convenience.
So now, can achieve the goal via the following method? What are the restrictions?
Macro Macro10
_s=
;static partial class Functions {
;,public static string Main2(string name) {
;,,string r = $"hello {name}";
;,,Console.WriteLine(r);
;,,return r;
;,}
;}
;Todo:
;Write the _s variable text to the class file "HSFun_Temp" in LA.
_s=LaHttpCall("Main2" "name=Lisa"); out _s
It would be great if this feature can be implemented, as there are many other possibilities for it.
Posts: 12,073
Threads: 140
Joined: Dec 2002
Then the C# file must be separate script. It cannot be part of the server script. The server must use script.run to compile and launch it, and it runs in separate process. Slower than with C# compiler.
Posts: 1,031
Threads: 246
Joined: Jul 2022
06-21-2023, 01:47 PM
(This post was last modified: 06-21-2023, 01:52 PM by Davider.)
The execution speed is very fast. Below demo are the manual operation steps. What I mean is to implement the method of programming the manual operation function (maybe I misunderstood it)
I don't know how to program in LA to achieve the following: receive the
variable and write its value to the
script.
Posts: 12,073
Threads: 140
Joined: Dec 2002
I guess it executes old code, that is why fast.
Posts: 12,073
Threads: 140
Joined: Dec 2002
var path = folders.sourceCode() + @"\Script name.cs";
print.it(path);
//filesystem.saveText(path, receivedCode);
Posts: 1,031
Threads: 246
Joined: Jul 2022
06-21-2023, 02:43 PM
(This post was last modified: 06-21-2023, 03:02 PM by Davider.)
I executed successfully using the following method
Macro Macro10
_s=
;static partial class Functions {
;,public static string Main2(string name) {
;,,string r = $"hello {name}";
;,,Console.WriteLine(r);
;,,return r;
;,}
;}
;Todo:
;Write the _s variable text to the class file "HSFun_Temp" in LA.
_s.setfile("$documents$\LibreAutomate\Main\files\HTTP\@HttpServer\HSFun_Temp.cs")
_s=LaHttpCall("Main2" "name=Lisa"); out _s
Quote:
I guess it executes old code, that is why fast.
How to delete a temporary generated DLL?
So it looks like QM can remotely operate QM and LA on another computer
It may be simpler to use the following method. How is it more reliable to receive parameters and write files in LA?
Macro Macro10
_s=
;static partial class Functions {
;,public static string Main2(string name) {
;,,string r = $"hello {name}";
;,,Console.WriteLine(r);
;,,return r;
;,}
;}
_s=LaHttpCall("Main2" F"cs={_s}" "name=Lisa"); out _s
;or
_s=LaHttpCall(F"cs={_s}" "Fun=Main2" "name=Lisa"); out _s
Posts: 12,073
Threads: 140
Joined: Dec 2002
06-21-2023, 03:03 PM
(This post was last modified: 06-21-2023, 03:04 PM by Gintaras.)
Quote:How to delete a temporary generated DLL?
There is no temporary dll that can be deleted.
Impossible to make faster in this way.
Posts: 1,031
Threads: 246
Joined: Jul 2022
06-21-2023, 11:03 PM
(This post was last modified: 06-21-2023, 11:13 PM by Davider.)
Thank you very much for your sharing. It's awesome that we don't need to download the compiler through nuget anymore!
In order to speed up the execution, I converted the CsScript class to a library and generated a dll.
Then I created a function named "Temp" and executed the sample code below. The speed is very fast,
however, I don't know how to make it support various types of parameters and return values. The following is the operation demonstration.
If it could be simplified to the following way of calling, it would be very convenient.
out LaHttpCall(F"code={_s}" "fun=Add" "a=6" "b=7")
out LaHttpCall(F"code={_s}" "fun=Hi" "name=Lisa")
Macro Macro7
_s=
;{}public class Class1
;{
;,public static int Add(int a, int b)
;,{ return a + b; }
;}
out LaHttpCall("Temp" F"code={_s}" "cla=Class1" "fun=Add" "a=6" "b=7")
;__________________________________________________________________Todo: make HSFun_Temp.cs support various types of parameters and return values
_s=
;{}public class Class8 {
;,public static string Hi(string name) {
;,,string r = $"hello {name} ";
;,,Console.WriteLine(r);
;,,return r;
;,}
;}
;out LaHttpCall("Temp" F"code={_s}" "cla=Class8" "fun=Hi" "name=Lisa") ;;Todo:
// class "HSFun_Temp.cs"
/*/ r CsScript.dll; /*/
//Todo: make Temp support various types of parameters and return values
static partial class Functions {
public static int Temp(string code, string cla, string fun, int a, int b) {
var c = CsScript.Compile(code);
var f = c.GetMethod<Func<int, int, int>>(cla, fun);
return f(a, b);
}
}
Posts: 1,031
Threads: 246
Joined: Jul 2022
06-22-2023, 10:40 AM
(This post was last modified: 06-22-2023, 10:54 AM by Davider.)
How to modify the GetMethod function to automatically obtain the type and quantity of parameters and return values?
I have searched for a lot of information and still haven't found a solution. It is difficult to understand the usage of delegates here.
_____________________________________________________________________________________________
string code = """
{}public class Class1
{
public static int Add(int a, int b)
{ return a + b; }
}
""";
var c = CsScript.Compile(code);
var f = c.GetMethod <Func<int, int, int>>("Class1", "Add");
print.it(f( 2, 5));
_____________________________________________________________________________________________
string code = """
{}public class Class2
{
public static string Join(string a, string b, int c)
{ return a + b + c; }
}
""";
var c = CsScript.Compile(code);
var f = c.GetMethod <Func<string, string, int, string>>("Class2", "Join");
print.it(f( "hello ", "world ", 123));
_____________________________________________________________________________________________
string code = """
{}public class Class3 {
public static string Hi(string name) {
string r = $"hello {name} ";
return r;
}
}
""";
var c = CsScript.Compile(code);
var f = c.GetMethod <Func<string, string>>("Class3", "Hi");
print.it(f( "Lisa"));
Http server Functions Corresponding modifications are also required
static partial class Functions {
public static int Temp(string code, string cla, string fun, xxx) {
var c = CsScript.Compile(code);
var f = c.GetMethod <Func<xxx>>(cla, fun);
return f( xxx);
}
}
Posts: 12,073
Threads: 140
Joined: Dec 2002
06-22-2023, 05:45 PM
(This post was last modified: 06-22-2023, 05:47 PM by Gintaras.)
This thread is a collection of old posts from other threads.
The solution is here: https://www.libreautomate.com/forum/show...1#pid36871
Posts: 1,031
Threads: 246
Joined: Jul 2022
06-23-2023, 01:05 AM
(This post was last modified: 06-23-2023, 01:08 AM by Davider.)
thank you so much!
I tested the code, it runs very fast and well.
Can you add code for the following two scenarios? This makes the application more versatile
Macro case1
;If the first line of the code starts with /*/, automatically parse the referenced assembly
str code=
;/*/ nuget -\EPPlus; /*/
;using OfficeOpenXml;
;
;public class C {
;,public static void setCell(string f, string v) {
;,,ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
;,,
;,,string file = folders.Downloads + f;
;,,using (var package = new ExcelPackage(new FileInfo(file))) {
;,,,var sheet = package.Workbook.Worksheets[0];
;,,,var s = sheet.Cells["A1"].Value;
;,,,print.it(s);
;,,,sheet.Cells["A1"].Value = v;
;,,,package.Save();
;,,}
;,}
;}
out LaHttpCall("Code" F"code={code}" "fun=C.setCell" "f=Sample.xlsx" "v=new value")
Macro case2
;When there are no classes and functions in the code, top-level statements can be executed directly.
str code=
;/*/ nuget -\EPPlus; /*/
;using OfficeOpenXml;
;
;ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
;
;string file = folders.Downloads + "Sample.xlsx";
;using(var package = new ExcelPackage(new FileInfo(file))) {
;,var sheet = package.Workbook.Worksheets[0];
;,var s = sheet.Cells["A1"].Value;
;,print.it(s);
;,sheet.Cells["A1"].Value = "new value";
;,package.Save();
;}
out LaHttpCall("Code" F"code={code}" "fun=")
Posts: 12,073
Threads: 140
Joined: Dec 2002
Also get the new versions of HTTP server, HTTP client and C# compiler codes from the forum.
|