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

Post your working scripts, libraries and tools
burque505
Posts: 1069
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: 1540
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 25 times
ovidiugabriel
Posts: 4
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: 6657
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

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: 1540
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: 1069
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: 485
Joined: 13 Feb 2017, 13:44
GitHub: DelPyth
Location: Somewhere in the US

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:
burque505
Posts: 1069
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: 4742
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: 1069
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: 4742
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: 1069
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.

Return to “Scripts and Functions”

Who is online

Users browsing this forum: mattdoofus, TAC109 and 57 guests