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

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

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

02 Jul 2018, 08:22

Can I inquire why you need that library to work with html?
tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

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

02 Jul 2018, 08:31

I wonder if ComObjCreate("HTMLFile") is reliable, due to different IE browser version. Although I have a function like this:

Code: Select all

html2dom(ByRef html, RemoveHeadAndImg = true)
{
	if RemoveHeadAndImg {
		html := RegExReplace(html, "`as)<head>.*?</head>")
		html := RegExReplace(html, "<img .*?>")
	}
	html := "<!doctype html><meta http-equiv=""X-UA-Compatible"" content=""IE=edge"">" . html

	static doc := ComObjCreate("HTMLFile")
	doc.open()
	doc.write(html)
	doc.close()
	
	While !(doc.Readystate = "Complete")
		Sleep, 10
	
	return doc
}
User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

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

02 Jul 2018, 08:39

I would think that should cover most use cases. Otherwise, you'll just have to code around certain DOM methods not being available on lower IE versions.
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

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

07 Jul 2018, 01:17

tmplinshi wrote:Can someone tell me why this doesn't work?
Define "work" and "doesn't work".

I assume an XDocument is an object, not a string or number, and therefore will show nothing in the MsgBox even if the script is successful.
tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

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

07 Jul 2018, 02:19

The error message is in Chinese language, so I didn't include the message, my bad, I was too lazy.
I have changed the OS language to English, the error was:
---------------------------
gumbo test.ahk
---------------------------
Error in #include file "D:\code\AutoHotkey\Lib\Clr.ahk":
0x80131513 -
Source: mscorlib
Description: Constructor on type 'Gumbo.Wrappers.GumboWrapper' not found.
HelpFile: (null)
HelpContext: 0

Specifically: CreateInstance_3

Line#
029: }
032: {
033: if !(argCount := Args.MaxIndex())
034: Return,Assembly.CreateInstance_2(TypeName, true)
036: vargs := ComObjArray(0xC, argCount)
037: Loop,argCount
038: vargs[A_Index-1] := Args[A_Index]
---> 042: Return,Assembly.CreateInstance_3(TypeName, true, 0, null, vargs, null, Array_Empty)
043: }
046: {
047: Return,CLR_CompileAssembly(Code, References, "System", "Microsoft.CSharp.CSharpCodeProvider", AppDomain, FileName, CompilerOptions)
048: }
051: {
052: Return,CLR_CompileAssembly(Code, References, "System", "Microsoft.VisualBasic.VBCodeProvider", AppDomain, FileName, CompilerOptions)
053: }

Continue running the script?
---------------------------
Yes No
---------------------------
The error was caused by the 3rd line:

Code: Select all

testHtml := "<html><body class=""gumbo"">Boo!</body></html>"
GumboBindings := Clr_LoadLibrary("Gumbo.Bindings.dll")
gumbo := Clr_CreateObject(GumboBindings, "Gumbo.Wrappers.GumboWrapper", testHtml)

MsgBox, % gumbo.ToXDocument()
Edit: wait, why the error is from Source: mscorlib but not Gumbo.Bindings.dll?
https://github.com/rgripper/GumboBindings wrote:Console.WriteLine(gumbo.ToXDocument()); // to XDocument
I am not sure but I guess XDocument is a string.
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

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

07 Jul 2018, 18:29

It is XDocument, not String. I think it is not common C# practice to make simple type aliases, if such is even possible (like the C++ typedef). Even if the content of XDocument is text, at the very least it is an object which contains a string. If you can get the constructor call to work, you can probably verify the type of the object with ComObjType(xdoc, "Class"), or just call xdoc.ToString().

I believe the constructor you want to call is one with an optional parameter. I have not used C# since 2.0, and optional parameters were added in 4.0. I have read that COM callable wrappers support optional parameters, but in this case we are not calling that method directly; we are calling Assembly.CreateInstance_3 (3rd overload of CreateInstance). You probably need to specify all of the parameters, including the optional one, which I think can just be null (ComObject(13,0)).
burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

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

07 Jul 2018, 19:14

Thank you, lexikos. That is what I needed for EPPlus to get a chart onto a worksheet.
ComObject(13,0) was the missing parameter needed for the call.

Code: Select all

chart := ws.Drawings.AddChart("Pie", 5, ComObject(13,0))
This will help me out with this topic and the related topic here, where tmplinshi has been of invaluable assistance. I haven't gotten a series into the chart yet, but soon.You've provided a missing building block. Thanks again.
EDIT: Chart series now added also.
Regards,
burque505
tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

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

08 Jul 2018, 10:55

Thanks lexikos! Good to know ComObject(13,0) for null parameters, that's a useful info for using CLR.ahk.

Code: Select all

gumbo := Clr_CreateObject(GumboBindings, "Gumbo.Wrappers.GumboWrapper", testHtml, ComObject(13, 0))
But adding to it, another error occurred :|
---------------------------
gumbo test.ahk
---------------------------
Error in #include file "D:\code\AutoHotkey\Lib\Clr.ahk":
0x80131604 -
Source: mscorlib
Description: Exception has been thrown by the target of an invocation.
HelpFile: (null)
HelpContext: 0

Specifically: CreateInstance_3

Line#
029: }
032: {
033: if !(argCount := Args.MaxIndex())
034: Return,Assembly.CreateInstance_2(TypeName, true)
036: vargs := ComObjArray(0xC, argCount)
037: Loop,argCount
038: vargs[A_Index-1] := Args[A_Index]
---> 042: Return,Assembly.CreateInstance_3(TypeName, true, 0, null, vargs, null, Array_Empty)
043: }
046: {
047: Return,CLR_CompileAssembly(Code, References, "System", "Microsoft.CSharp.CSharpCodeProvider", AppDomain, FileName, CompilerOptions)
048: }
051: {
052: Return,CLR_CompileAssembly(Code, References, "System", "Microsoft.VisualBasic.VBCodeProvider", AppDomain, FileName, CompilerOptions)
053: }

Continue running the script?
---------------------------
Yes No
---------------------------
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

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

11 Jul 2018, 21:57

An exception was thrown by the constructor. You probably can't call this constructor from unmanaged (COM) code. I'd guess that you can't use VT_UNKNOWN (13) for this null value since it is a nullable value type, not an object. You may need to use some helper code (C# or VB).
LayoutKind.Automatic
Indicates that the common language runtime is free to reorder the members of the type for efficiency. However, when a value type is passed to unmanaged code, the layout of the members is predictable. An attempt to marshal such a structure automatically causes an exception.
https://docs.microsoft.com/en-us/dotnet ... g-behavior
tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

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

12 Jul 2018, 11:40

hmm.. that's difficult for me to continue, I'm giving up on this dll. Thanks again.
burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

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

15 Jul 2018, 08:05

Sorry to flog a dead horse here, but I'm having trouble with such a number of third-party (i.e. non-Microsoft) DLLs that I'm still after information to solve this particular one. My hope is that whatever ends up solving this problem will help with my other problem Dlls (i.e. ClosedXml, OfficeOpenXml, SpreadsheetLight, DocX/Xceed.Words.Net, and several others. For all of these, I have tried VB.Net code, C# code, and Clr_LoadLibrary ()).
Using the same code tmplinshi does, i.e.

Code: Select all

gumbo := Clr_CreateObject(GumboBindings, "Gumbo.Wrappers.GumboWrapper", testHtml, ComObject(13, 0))
, I get this error output from the output window of Scite4Ahk after hitting "No" to continue running script:

Code: Select all

Unhandled Exception: System.BadImageFormatException: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)
   at Gumbo.NativeMethods.gumbo_destroy_output(GumboOptions& options, IntPtr output)
   at Gumbo.Wrappers.GumboWrapper.Dispose()
   at Gumbo.Wrappers.GumboWrapper.Finalize()
I will be grateful for any help understanding this. I have followed through at this link, and have tried recompiling GumboWrappers.dll from source (epic fail, nearly 2000 errors in code on github when compiling with VS 2015 or VS 2017, including over 200 references to "dotnet5.4")). Is it possible the culprit is simply a bad GumboWrappers.DLL?
Regards,
burque505
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

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

17 Jul 2018, 02:03

Probably the wrong .NET Framework version, or bitness (32-bit vs 64-bit, though I think some assemblies are both).
burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

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

17 Jul 2018, 11:41

Thanks. I used dumpbin /headers to get the following info. Unless I'm mistaken, both dlls are 32-bit, and GumboBindings.dll was compiled against DotNet v4.52.
gumbo.dll
Spoiler
Gumbo.Bindings.dll
Spoiler
Regards,
burque505
User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

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

17 Jul 2018, 13:10

I have certainly seen instances where x64 AHK does not seem to like loading x86 DLLs, so further to what Lexikos said, if you haven't already, try x86 AHK
If memory serves actually, when I came across something similar, it was when my AHK code was loading my C# Interception wrapper via CLR, then my Interception wrapper invoked the unmanaged Interception DLL.
It turns out that if the bitness of that DLL did not match the bitness of AHK.... boom.
ie the GumboWrapper DLL may be AnyCPU, but the DLL that it is ultimately wrapping may not be, and I think needs to match the bitness of AHK.

FYI, link to the GumboWrapper ctor:
https://github.com/rgripper/GumboBindin ... per.cs#L46

Hope this helps
burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

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

17 Jul 2018, 13:49

I appreciate the advice. The very first thing I did, when the OP on GumboBindings came out actually, was try x86 AHK, with no change in results at all. As the spoilers above show, both gumbo.dll and GumboBindings.dll are 32 bit, and GumboBindings.dll was compiled against dotnet 4.52.
It doesn't appear that GumboBindings.dll is maintained, both from the length of time since a commit and because the code contains literally hundreds of errors. [EDIT: I should say, hundreds of errors when compiled with VS 2017 or VS 2015 - more with one than the other, don't remember which had more. I don't have an earlier version of VS to test it, maybe it would compile fine with an earlier version.]
Also, the GumboBindings library itself loads without complaint. Here's the output from ComObjType for it:

Code: Select all

GumboBindings's class is Assembly
Name is _Assembly
CLSID is {28E89A9F-E67D-3028-AA1B-E5EBCDE6F3C8}
VT is 9
I just can't create an object from the loaded library.
Regards,
burque505
User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

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

17 Jul 2018, 13:55

In the Ctor, the 2nd param is a GumboWrapperOptions class, which is here: https://github.com/rgripper/GumboBindin ... per.cs#L11

Could you not create one of those? In HotVoice I have factory methods that return classes, and the AHK code can quite happily use these to new up a class, then set some properties etc, and pass it back to the C# code
burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

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

17 Jul 2018, 16:09

Thanks, evilC, let me give that a try.
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

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

19 Jul 2018, 22:33

evilC wrote:I have certainly seen instances where x64 AHK does not seem to like loading x86 DLLs,
There is no 64-bit executable that can load a 32-bit dll for execution.
evilC wrote:In the Ctor, the 2nd param is a GumboWrapperOptions class,
There is no such class. It is a struct. I do not think you can pass this struct between managed and unmanaged code. See my previous post.
burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

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

20 Jul 2018, 16:38

x64 Unicode AHK loads 32-bit EPPlus.dll fine.
Spoiler
Everything seen here and here runs with 64-bit AHK loading this 32-bit DLL.

HOWEVER: According to this page what lexikos says is 100% correct:
However, 32-bit processes cannot load 64-bit DLLs for execution, and 64-bit processes cannot load 32-bit DLLs for execution. This restriction does not apply to DLLs loaded as data files or image resource files; for more information, see LoadLibraryEx.
I got the results in the spoiler following instructions here. Unless that's wrong, the DLL I'm using (which was compiled for "Any CPU"), is 32-bit.

EDIT: This post describes workarounds and the interaction of IPC and COM. I wonder what is going on "under the hood" to allow me to run this 32-bit DLL with 64-bit AHK without (at least intentionally) any effort by me to provide for this functionality in my code.

What am I missing?
Regards,
burque505
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

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

20 Jul 2018, 17:10

CLR assemblies contain CLR IL code and metadata, not compiled machine code. Your file is neither 32-bit nor 64-bit.

Setting the target platform to something other than "Any CPU" only restricts how the file can be loaded. See Visual Studio .NET Platform Target Explained : Visual Studio Hacks.

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: gwarble, JoeWinograd and 133 guests