Page 5 of 8

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

Posted: 23 Jun 2017, 05:44
by sancarn
evilC wrote:I couldn't work out if it was possible, in the end I just returned an array of strings
Indeed, supposedly you can do list.Cast<object>().ToArray()... But I would assume there must be a way to extract the variables directly...

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

Posted: 23 Jun 2017, 06:33
by qwerty12
sancarn wrote:How do you parse a List object from CLR to AHK?

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
#Include %A_ScriptDir%\CLR.ahk

code =
(
    Imports System
    Imports System.Collections.Generic
    Class MainClass
        Function TestList() as List(Of String)
            return New List(Of String)(New String(){"This","is","a","list"})
        end function
    end class
)

asm := CLR_CompileVB(code, "System.dll")
obj := CLR_CreateObject(asm,"MainClass")
list := obj.TestList()

ICollection := ComObject(9, ComObjQuery(list, "{DE8DB6F8-D101-3A92-8D1C-E72E5F10E992}"), 1)
IList := ComObject(9, ComObjQuery(ICollection, "{7BCFA00F-F764-3113-9140-3BBD127A96BB}"), 1)
Loop % ICollection.Count()
	MsgBox % IList.Item(A_Index - 1)

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

Posted: 23 Jun 2017, 06:48
by sancarn
qwerty12 wrote:
sancarn wrote:How do you parse a List object from CLR to AHK?

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
#Include %A_ScriptDir%\CLR.ahk

code =
(
    Imports System
    Imports System.Collections.Generic
    Class MainClass
        Function TestList() as List(Of String)
            return New List(Of String)(New String(){"This","is","a","list"})
        end function
    end class
)

asm := CLR_CompileVB(code, "System.dll")
obj := CLR_CreateObject(asm,"MainClass")
list := obj.TestList()

ICollection := ComObject(9, ComObjQuery(list, "{DE8DB6F8-D101-3A92-8D1C-E72E5F10E992}"), 1)
IList := ComObject(9, ComObjQuery(ICollection, "{7BCFA00F-F764-3113-9140-3BBD127A96BB}"), 1)
Loop % ICollection.Count()
	MsgBox % IList.Item(A_Index - 1)
Well I never! This is great to know!

I myself was looking into [this for a possible solution](https://maul-esel.github.io/tutorials/C ... faces.html) but couldn't find the header file for ICollection. By the way... How did you get/find the IID for ICollection and IList?

EDIT:

I didn't realize that all interfaces and IIDs are stored in HKEY_CLASSES_ROOT\Interface\!! This is really useful, though I need to find a quicker way of searching for it :P Perhaps a function could even be created to query the registry for an interface given by name! :o

Edit 2:

Something along the lines of this:

Code: Select all

findIID(name){
	Loop, Reg, HKEY_CLASSES_ROOT\Interface\, KV
	{
		RegRead, interface, HKEY_CLASSES_ROOT\Interface\%A_LoopRegName%
		if (interface = name)
			return A_LoopRegName
		
	}
}

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

Posted: 23 Jun 2017, 06:59
by qwerty12
sancarn wrote:By the way... How did you get/find the IID for ICollection and IList?
I took your idea of using ComObjType, but with CLSID as Param2 instead and got given a GUID for Object. When Googling it, the results indicated I could find what I was looking for in mscorlib.tlb, so I used oleview.exe on said file. I then took a guess on IList and ICollection being the appropriate interfaces...

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

Posted: 04 Jul 2017, 11:21
by evilC
Anyone got any ideas why this code throws an error?
Is inheritance not supported?

Code: Select all

c# =
(
    class Foo : Bar {
        public int Test() {
            return 2;
        }
    }
	
	class Bar {
	
	}
)
asm := CLR_CompileC#(c#)
obj := CLR_CreateObject(asm, "Foo")
msgbox % obj.Test()
return

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

Posted: 05 Jul 2017, 02:31
by lexikos
Add the public modifier to your classes.

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

Posted: 05 Jul 2017, 04:22
by evilC
Hmm, I swear the original code I was using had public modifiers for all the classes, but I could be wrong. Will double-check tonight, thanks!

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

Posted: 05 Jul 2017, 15:18
by evilC
Yeah, it wasn't just the lack of public, I rewrote the code as a simple AHK script using dynamic compilation, and obviously I simplified too far...

I tried to repro with another dynamically compiled sample, but I could not. Upon further investigation, there appears to be a difference in behavior between pre-compiled DLLs and dynamically compiled code.

Code: Select all

#SingleInstance force
#NoEnv

#include <CLR>

c# =
(
public class Outer
{
    public InnerOne innerOne = new InnerOne();

    public class InnerOne : InnerBase
    {
        public string Test()
        {
            return "OK";
        }
    }

    public class InnerBase
    {

    }
}
)
asm := CLR_CompileC#(c#)
obj := CLR_CreateObject(asm, "Outer")
msgbox % obj.innerOne.Test()
return

^Esc::
	ExitApp
This code works fine, however if you make a project in VS using the same C# code and compile, then calling obj.innerOne.Test() throws an error.
In the compiled version, if you change public class InnerOne : InnerBase to public class InnerOne, then the problem goes away.
Most odd.

SLN attached

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

Posted: 05 Jul 2017, 22:59
by lexikos
My guess is that it has something to do with COM visibility. A quick search turned up some details supporting this:
  • Public classes are COM visible by default.
  • Visual Studio overrides this default, making it false.
https://stackoverflow.com/questions/156 ... m-exposure

See Properties\AssemblyInfo.cs.

Code: Select all

// Setting ComVisible to false makes the types in this assembly not visible 
// to COM components.  If you need to access a type in this assembly from 
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
I think that some methods used by CLR.ahk bypass COM visibility; e.g. because Assembly and Type are COM visible.

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

Posted: 06 Jul 2017, 04:29
by evilC
OK, that would make some sense, so the difference is in the way VS packages the code.
Will give this a try, thanks.

I am thinking that it may make some sense to have some sort of CLR for AHK cribsheet / docs?
eg nuggets of info like this, and maybe some basic patterns to show people how to achieve some common goals (eg how to do callbacks, stuff like the list example from a couple of posts back, etc)
I am happy to contribute, but am conscious that my lack of depth of knowledge in this area may mean some hokey code or bad assumptions, is anyone else willing to pitch in?

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

Posted: 06 Jul 2017, 14:03
by evilC
I can confirm that setting ComVisible to true fixed this problem.
Many thanks, I doubt I would have got there alone ;)

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

Posted: 07 Jul 2017, 14:41
by sancarn
evilC wrote:OK, that would make some sense, so the difference is in the way VS packages the code.
Will give this a try, thanks.

I am thinking that it may make some sense to have some sort of CLR for AHK cribsheet / docs?
eg nuggets of info like this, and maybe some basic patterns to show people how to achieve some common goals (eg how to do callbacks, stuff like the list example from a couple of posts back, etc)
I am happy to contribute, but am conscious that my lack of depth of knowledge in this area may mean some hokey code or bad assumptions, is anyone else willing to pitch in?

This would be extremely handy, I agree.
Would be willing to pitch in but I fear I am more inexperienced than yourself xD

Where to make it? Perhaps on github like JXA cookbook. Somewhere where anyone can just go and edit in some examples and stuff. :)

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

Posted: 07 Jul 2017, 14:55
by evilC
Oh, and @Lexikos - is there any chance of building CLR into AHK?

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

Posted: 07 Jul 2017, 16:44
by lexikos
No. I'd rather not have second-rate CLR support built-in, and that's the only kind possible via COM callable wrappers.

Putting that aside, I've said before that I don't even use CLR.ahk, and I have no interest in using .NET. So for me, re-implementing CLR support in a different form with the same limitations would be a complete waste of time.

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

Posted: 07 Jul 2017, 16:51
by evilC
Care to elaborate on the "second-rate" comment?

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

Posted: 07 Jul 2017, 17:09
by lexikos
Haven't you tried calling overloaded or static methods? There are also enumerations, static fields, and probably other things that require Reflection or some intermediary .NET code.

Though for static methods, one can possibly wrap the Type in a dynamic object.

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

Posted: 08 Jul 2017, 08:08
by slimpickens
Hi, I'm trying to launch a script which #includes CLR.ahk and I get an error "Functions cannot contain functions" at line 11: CLR_LoadLibrary(AssemblyName, AppDomain=0)
I'm using AHK1.1.26 on 64bit windows.

Any idea?

Thanks!

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

Posted: 08 Jul 2017, 21:44
by lexikos
You have mismatched braces in your script, or you have used #include inside a function. (This is not specific to CLR.ahk; it would happen with any file containing a function definition.)

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

Posted: 09 Jul 2017, 05:15
by slimpickens
lexikos wrote:You have mismatched braces in your script, or you have used #include inside a function. (This is not specific to CLR.ahk; it would happen with any file containing a function definition.)
Big Thanks!
I didn't believe it but you where right, kind-of, one of the imported scripts was being treated as commented out.

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

Posted: 06 Oct 2017, 17:00
by Mper
Thank you very much lexikos, you saved my day with this insane .ahk !