Page 7 of 11

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

Posted: 02 Jul 2018, 08:22
by kczx3
Can I inquire why you need that library to work with html?

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

Posted: 02 Jul 2018, 08:31
by tmplinshi
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
}

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

Posted: 02 Jul 2018, 08:39
by kczx3
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.

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

Posted: 07 Jul 2018, 01:17
by lexikos
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.

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

Posted: 07 Jul 2018, 02:19
by tmplinshi
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.

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

Posted: 07 Jul 2018, 18:29
by lexikos
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)).

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

Posted: 07 Jul 2018, 19:14
by burque505
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

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

Posted: 08 Jul 2018, 10:55
by tmplinshi
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
---------------------------

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

Posted: 11 Jul 2018, 21:57
by lexikos
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

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

Posted: 12 Jul 2018, 11:40
by tmplinshi
hmm.. that's difficult for me to continue, I'm giving up on this dll. Thanks again.

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

Posted: 15 Jul 2018, 08:05
by burque505
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

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

Posted: 17 Jul 2018, 02:03
by lexikos
Probably the wrong .NET Framework version, or bitness (32-bit vs 64-bit, though I think some assemblies are both).

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

Posted: 17 Jul 2018, 11:41
by burque505
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

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

Posted: 17 Jul 2018, 13:10
by evilC
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

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

Posted: 17 Jul 2018, 13:49
by burque505
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

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

Posted: 17 Jul 2018, 13:55
by evilC
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

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

Posted: 17 Jul 2018, 16:09
by burque505
Thanks, evilC, let me give that a try.

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

Posted: 19 Jul 2018, 22:33
by lexikos
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.

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

Posted: 20 Jul 2018, 16:38
by burque505
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

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

Posted: 20 Jul 2018, 17:10
by lexikos
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.