.NET Framework Interop (CLR, C#, VB)

Post your working scripts, libraries and tools for AHK v1.1 and older
burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

Re: .NET Framework Interop (CLR, C#, VB)

20 Jul 2018, 17:22

Thanks, lexikos, that's enlightening.
Klarion
Posts: 176
Joined: 26 Mar 2019, 10:02

Re: .NET Framework Interop (CLR, C#, VB)

08 Apr 2019, 08:38

I have a post at "Ask For Help" section
But, got nothing
If I was lucky enough, I could have some Help here, as a last resort.

It is related mainly SQLite, C# and lastly AHK
It is my first trying, to grab records count, the easiest one in that field.

SQLite via C# got an Error
https://www.autohotkey.com/boards/viewtopic.php?f=76&t=63358

I'm suspect, there should be some procedure hidden to me. I do not know what that is though clearly.

Thanks
Klarion
Posts: 176
Joined: 26 Mar 2019, 10:02

Re: .NET Framework Interop (CLR, C#, VB)

08 Apr 2019, 08:43

ah
I have wrote very simple codes

One code is to make a MS Word file (docx) without using its own application, it is using OpenXML style.
The other is to make a MS Excel file (xlsx) without using its own application, it is using OpenXML style too.

AHK/CLR/OpenXml - Office documents w/o MS Excel
https://www.autohotkey.com/boards/viewtopic.php?f=74&t=63344

AHK/CLR/OpenXml - Office docs w/o Office (not main post, but a comment at the 2nd)
https://www.autohotkey.com/boards/viewtopic.php?p=271001#p271001
tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

Re: .NET Framework Interop (CLR, C#, VB)

19 Jun 2019, 02:21

I got an error when running from 64-bit AutoHotkey: (works fine from 32-bit AutoHotkey.)

Code: Select all

---------------------------
GetScreen.ahk
---------------------------
Error:  0x80004003 - Invalid pointer
Source:		mscorlib
Description:	Value cannot be null.
Parameter name: source
HelpFile:		(null)
HelpContext:	0

Specifically: GetScreen

	Line#
	004: RunAsAdmin()  
	006: FileRead,c#,MirrSharp.cs
	007: dlls := "System.dll|System.ComponentModel.dll|System.Data.dll|System.Drawing.dll|System.Reflection.dll|System.Windows.Forms.dll|System.Runtime.InteropServices.dll|System.Threading.dll"
	008: asm := CLR_CompileC#( c#, dlls )
	010: _mirror := CLR_CreateObject(asm, "MirrSharp.Driver.DesktopMirror")
	011: _mirror.Load(), Sleep(1000)  
	012: _mirror.Connect(), Sleep(1000)  
--->	014: _mirror.GetScreen().Save("screenshot.png")  
	016: _mirror.Disconnect()  
	017: _mirror.Unload()  
	018: _mirror.Dispose()  
	020: ExitApp
	022: {
	023: Sleep,Delay
	024: }

Continue running the script?
---------------------------
Yes   No   
---------------------------
The error was caused by line 421 of the file MirrSharp.cs:
Marshal.Copy(getChangesBuffer.UserBuffer, data, 0, bytes);
Because when I put return result; above it, error disappeared, but put below it, the error occured.

You'll need to install DFMirage driver first to run the script.
The code of MirrSharp.cs was copied from http://www.demoforge.com/sdk/mirrsharp.zip.

Appreciate any help.
Attachments
MirrSharp_GetScreen.zip
(5.35 KiB) Downloaded 191 times
ovidiugabriel
Posts: 9
Joined: 22 Jul 2018, 14:19

Re: .NET Framework Interop (CLR, C#, VB)

18 Jul 2019, 09:49

Hello, I am not an expert in .NET/CLR internals, maybe my question is dumb. :oops:

How does the compiler know where to lookup for DLL in the References list?

I am asking because I searched on my computer and I have 19 instances of WindowsBase.dll, and 10 instances of DocumentFormat.OpenXml.dll
Until now AHK script is able to load them only if they are copied into the current folder - which is not feasible for my case as you can see.

I installed DocumentFormat.OpenXml.dll using version 2.9.1 using NuGet.
I would like to load required references in a standard/reliable manner and not specifying the path manually. :?
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: .NET Framework Interop (CLR, C#, VB)

19 Jul 2019, 23:44

It may depend on whether you specify a full path, version number, etc. and which version of the framework you have loaded. A reference may bind to an assembly which is already loaded (such as System.dll), or the assembly may be loaded from the Global Assembly Cache or from a file elsewhere. See How the Runtime Locates Assemblies | Microsoft Docs.
tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

Re: .NET Framework Interop (CLR, C#, VB)

19 Aug 2019, 02:52

Example: Run PowerShell Script without powershell.exe

Code: Select all

cSharp =
(
using System.Text;
using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Management.Automation.Runspaces;

public class ps
{
	public string RunScript(string scriptText)
	{
		Runspace runspace = RunspaceFactory.CreateRunspace();
		runspace.Open();

		Pipeline pipeline = runspace.CreatePipeline();
		pipeline.Commands.AddScript(scriptText);
		pipeline.Commands.Add("Out-String");

		Collection<PSObject> results = pipeline.Invoke();

		runspace.Close();
		return results[0].ToString();
		
		/*
		StringBuilder stringBuilder = new StringBuilder();
		foreach (PSObject obj in results)
		{
			stringBuilder.AppendLine(obj.ToString());
		}

		return stringBuilder.ToString();
		*/
	}
}
)

asm := CLR_CompileC#( cSharp, "System.Core.dll | C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Management.Automation\v4.0_3.0.0.0__31bf3856ad364e35\System.Management.Automation.dll" )
ps := asm.CreateInstance("ps")
MsgBox % ps.RunScript("echo hello")
MsgBox % ps.RunScript("Get-Service")

/*
psCode =
(
[Reflection.Assembly]::LoadFile("D:\Desktop\EPPlus.dll") | Out-Null
$xl = New-Object OfficeOpenXml.ExcelPackage
$ws = $xl.Workbook.Worksheets.Add("test")
$ws.Cells["A1"].Value = 123
$ws.Cells["A2"].Value = "test"
$xl.SaveAs("CreateByPS.xlsx")
)
msgbox % ps.RunScript(psCode)
*/
burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

Re: .NET Framework Interop (CLR, C#, VB)

22 Aug 2019, 13:44

@tmplinshi, very nice, thanks!
User avatar
Delta Pythagorean
Posts: 627
Joined: 13 Feb 2017, 13:44
Location: Somewhere in the US
Contact:

Re: .NET Framework Interop (CLR, C#, VB)

22 Aug 2019, 18:07

Haven't found this until today, so give me a break.

So, if I do some little magic with this and some DllCalls here and there, could it theoretically be possible to create DLL Libraries using AHK? :think:

[AHK]......: v2.0.12 | 64-bit
[OS].......: Windows 11 | 23H2 (OS Build: 22621.3296)
[GITHUB]...: github.com/DelPyth
[PAYPAL]...: paypal.me/DelPyth
[DISCORD]..: tophatcat

burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

Re: .NET Framework Interop (CLR, C#, VB)

22 Aug 2019, 18:15

Yes, you can create DLLs and executables.
I'll try to find one where I actually created an EXE that can be run, but take a look here.
I'll edit this if I find more stuff.
EDIT:
Found one. You'll need Xceed.Words.NET, which you can find here. Just unzip the NuGet package and grab the DLL out of the lib folder, put it in the script directory. Hopefully it will just work. (Notice I deleted the .exe after running, you don't need to do that. Use switches (read through the first post) to create a DLL instead).

Code: Select all

csharp=
(
using System;
using System.Diagnostics;
using System.Windows.Forms;
using Xceed.Words.NET;
using System.Drawing;
using System.Collections.Generic;
using System.Text.RegularExpressions;

class Script
{
    [STAThread]
    static void Main(string[] args)
    {
               //Get parameters
                string FirstName = "Benjamin";
                string LastName = "Adler";
                string Username = "Badler"; 

                //Get template

                string TemplateFileName = @"test2.docx";
                DocX template = DocX.Load(TemplateFileName);            

                //Replace macros with parameters
                template.ReplaceText("<FirstName>", FirstName, false, RegexOptions.Singleline, null, null, MatchFormattingOptions.ExactMatch);
                template.ReplaceText("<LastName>", LastName, false, RegexOptions.Singleline, null, null, MatchFormattingOptions.ExactMatch);
                //Save with new file name

                string newFile = string.Format(@"test_{0}.docx", Username);

                template.SaveAs(newFile);

    }
}


)

asm := CLR_CompileC#(csharp,"System.dll|System.Drawing.dll|System.Text.RegularExpressions.dll|System.Collections.dll|Microsoft.CSharp.dll|Xceed.Words.NET.dll|System.Windows.Forms.dll", 0, "DahkX4.exe", "/target:winexe")
RunWait, DahkX4.exe
sleep, 100
FileDelete, DahkX4.exe
FileDelete, DahkX4.pdb
ExitApp
User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: .NET Framework Interop (CLR, C#, VB)

11 Sep 2019, 12:14

I recently noticed qwerty12's post about parsing a List<T> from .NET code and had a stab at writing a wrapper class to handle it all, this is what I came up with so far - basically it lets you Count(), MaxIndex() etc as well as enumerate a List<T> as if it were an AHK array:

Code: Select all

#include CLR.ahk

code =
(
    using System.Collections.Generic;
	
    public class ListTest
    {
        public List<string> GetList()
        {
            return new List<string>{"One", "Two", "Three"};
        }
    }
)
asm := CLR_CompileC#(code)
cs := asm.CreateInstance("ListTest")

l := cs.GetList()

lw := new ListWrapper(l)

str := "Count(): " lw.Count() "`n"
str .= "MaxIndex(): " lw.MaxIndex() "`n"
str .= "Length(): " lw.Length() "`n"
for k, v in lw {
	str .= "Item " k ": " v "`n"
}
msgbox % str
return

; A class to wrap a List<T> coming from .NET
; Converts 0-based indexes to 1-based, provides enumerator, Count() etc
Class ListWrapper {
	__New(list){
		this.List := list
		; https://www.autohotkey.com/boards/viewtopic.php?p=155453#p155453
		this.ICollection := ComObject(9, ComObjQuery(this.List, "{DE8DB6F8-D101-3A92-8D1C-E72E5F10E992}"), 1)
		this.IList := ComObject(9, ComObjQuery(this.ICollection, "{7BCFA00F-F764-3113-9140-3BBD127A96BB}"), 1)
	}
	
	; Handle index lookups ([1], [2] etc)
	__Get(i){
		return this.IList.Item(i - 1)
	}
	
	; === Enumerator code to handle for loops
	; https://www.autohotkey.com/boards/viewtopic.php?f=7&t=7199
	_NewEnum(){
		this.i := 0
		return this
	}
	
	Next(ByRef k, ByRef v){
		this.i++
		if (this.i > this.Count()){
			return False
		}
		k := this.i
		v := this[k]
		return True
	}
	
	; ==== Count, MaxIndex etc
	Count(){
		return this.ICollection.Count()
	}
	
	MaxIndex(){
		return this.ICollection.Count()
	}
	
	Length(){
		return this.ICollection.Count()
	}
}
burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

Re: .NET Framework Interop (CLR, C#, VB)

11 Sep 2019, 12:57

@evilC, that works great. Thank you! This looks extendable to other types of collections. For those who might be wondering about a good place to get that IID data @qwerty12 and evilC use for

Code: Select all

Class ListWrapper {
	__New(list){
		this.List := list
		; https://www.autohotkey.com/boards/viewtopic.php?p=155453#p155453
		this.ICollection := ComObject(9, ComObjQuery(this.List, "{DE8DB6F8-D101-3A92-8D1C-E72E5F10E992}"), 1)
		this.IList := ComObject(9, ComObjQuery(this.ICollection, "{7BCFA00F-F764-3113-9140-3BBD127A96BB}"), 1)
	}
try this gist. About a 1MB text file. @sancarn, were you looking for a good place to find this stuff? Might save using mscorlib.tlb or oleview.exe. I would just post the file here, but I'm guessing that gist will be around quite a while. Thanks to hfiref0x for posting this for all to find!
Here's a spoiler (just a few dozen lines):
Spoiler
Regards,
burque505

EDIT: 16,225 CLSIDs in the file.
User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: .NET Framework Interop (CLR, C#, VB)

11 Sep 2019, 13:32

Thanks, how about maybe we create a repo on GitHub for CLR interop stuff where we can collect code snippets, tricks and tips?
Maybe also include some guides on how to set up Visual Studio .NET projects for easy use with AHK?
burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

Re: .NET Framework Interop (CLR, C#, VB)

11 Sep 2019, 13:45

Sounds like a great idea to me!
EDIT: I added a post about a little search tool here which is on GitHub.
bourdin07
Posts: 36
Joined: 23 Jun 2019, 12:57

Re: .NET Framework Interop (CLR, C#, VB)

12 Feb 2020, 12:30

It is possible with this CLR library to import NUget packages?

EDIT :
I found alternative but I have to register with gac via Developer Command Prompt. I d like without it.
bourdin07
Posts: 36
Joined: 23 Jun 2019, 12:57

Re: .NET Framework Interop (CLR, C#, VB)

13 Feb 2020, 15:05

I have a problem I don't know how to instantiate a struct System.DateTime

I tried :

Code: Select all

        asm := CLR.LoadLibrary("System.dll")
        DT := CLR.CreateObject(asm, "System.DateTime", 1987, 3, 23)
	MsgBox % DT.Ticks
Any tips please?
burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

Re: .NET Framework Interop (CLR, C#, VB)

13 Feb 2020, 17:15

@bourdin07 , please take a look at jNizM's extremely helpful DllCall github repository.
I think may you need DllCall instead of .NET Interop for this.
This is from jNiZm's github repository. If you are trying to get the ticks since March 23, 1987, it won't do that, but may help nonetheless.

Code: Select all

GetTickCount64()
{
    return DllCall("kernel32.dll\GetTickCount64", "UInt64")
}
MsgBox % GetTickCount64()
I'll keep digging to see if I get you any closer.
Regards,
burque505
bourdin07
Posts: 36
Joined: 23 Jun 2019, 12:57

Re: .NET Framework Interop (CLR, C#, VB)

15 Feb 2020, 18:31

@burque505 Thanks for the additionals DllCall methods
ahkrpa
Posts: 17
Joined: 16 Apr 2019, 17:34

Re: .NET Framework Interop (CLR, C#, VB)

16 Feb 2020, 13:01

@burque505 and @tmplinshi

Have benefited mightily from your insight around EPPlus and Excel. Hoping this is the right place to inquire after guidance on how to "Resize Table".

I have tried numerous permutations including the following; and unable to translate into AHK:
https://riptutorial.com/epplus/example/27209/adding-and-formating-a-table
https://stackoverflow.com/questions/34549597/expand-a-table-in-epplus-c-sharp

Apologies if this is out of band.
bourdin07
Posts: 36
Joined: 23 Jun 2019, 12:57

Re: .NET Framework Interop (CLR, C#, VB)

08 Mar 2020, 19:31

I try to rewrite a deprecated code found in this CLR lib :

Code: Select all

StringSplit, Refs, References, |, %A_Space%%A_Tab%
to

Code: Select all

Refs := StrSplit(References, "|", A_Space A_Tab)
what does these lines means?

Code: Select all

aRefs := ComObjArray(8, Refs0)

Loop % Refs0
    aRefs[A_Index-1] := Refs%A_Index%
But the compilation failed...

Code: Select all

"Message": 
"Error CS0234 on line 4: The type or namespace name 'Windows' does not exist in the namespace 'System' (are you missing an assembly reference?)

Error CS0234 on line 5: The type or namespace name 'Web' does not exist in the namespace 'System' (are you missing an assembly reference?)

Error CS0234 on line 6: The type or namespace name 'EnterpriseServices' does not exist in the namespace 'System' (are you missing an assembly reference?)

Error CS0246 on line 7: The type or namespace name 'Newtonsoft' could not be found (are you missing a using directive or an assembly reference?)"
Edit:
I found how to refactor:

Code: Select all

Refs := StrSplit(References, "|", A_Space A_Tab)
aRefs := ComObjArray(8, totalRefs := ObjMaxIndex(Refs))

loop % totalRefs
    aRefs[A_Index-1] := Refs[A_Index]
    ; print(aRefs[A_Index - 1])

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 116 guests