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

Post your working scripts, libraries and tools
hotkeyguy
Posts: 108
Joined: 11 Oct 2014, 12:22

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

25 Jul 2016, 16:30

Hello Lexikos,

some additional XPTable questions - I'm using AutoHotkey v1.1.23.06:
  1. ComObject(...), ComObjArray(...),ComObjError(...)
    Can't find anything in the help, only for v2: ComObject()
  2. Tried to set the width of the first column via col1.width := 100. Got an error 0x80131509. Found an hint here: C++ calling C# COM interop error: HRESULT 0x80131509 - Stack Overflow
    Even iWidth := col1.DefaultWidth didn't work.
    (Columns.Add( col4 := CLR_CreateObject( asm, "XPTable.Models.ImageColumn", "ImageColumn", 80 ) ) worked.)
  3. Tried to get the value of XPTable.Models.ColumnAlignment.Center:

    Code: [Select all] [Download] GeSHi © Codebox Plus

    oModels := CLR_CreateObject( asm, "XPTable.Models" )

    oModels1 := oModels
    oModels2 := oModels.ColumnAlignment
    oModels3 := oModels.ColumnAlignment.Center
    oModels is undefined (string).
  4. CLR and Reflection
    Do you have an simple example?

Many thanks and greetings
hotkeyguy
lexikos
Posts: 5329
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

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

25 Jul 2016, 23:07

I do not use XPTable, do not know its API, and am not interested in debugging it. I merely performed basic translation of C# code (years ago) and tested it. I don't even use CLR.ahk.
hotkeyguy wrote:ComObject(...), ComObjArray(...),ComObjError(...)
Can't find anything in the help,
Try again. ComObjArray and ComObjError are in the index. ComObject is listed as "ComObj...()" because of the "many-named" nature of the function in v1, but "ComObject" can easily be found by searching.
CLR_CreateObject( asm, "XPTable.Models" )
At a guess, I'd say XPTable.Models is a namespace, not a type name.
CLR and Reflection
Do you have an simple example
As I said, "There's an example in CLR_LoadLibrary (calling the static method Assembly.LoadFrom)." I'm not interested in using or teaching .NET. I suggest that you learn (in C# or VB) from any of the countless resources available on the Internet, and then apply that to AutoHotkey. Or just use C#/VB.
User avatar
megnatar
Posts: 63
Joined: 27 Oct 2014, 20:49
GitHub: Megnatar
Location: The Netherlands

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

26 Jul 2016, 13:08

Ooo sweet feature to the language :D. Thanks for this awesome library and the ongoing development of autohotkey!
payback87
Posts: 13
Joined: 31 Aug 2016, 01:55

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

15 Sep 2016, 13:27

Hey there,
I was just playing around with your cool library and wondered if it is possible to recreate Automating Lync with Lync SDK via the lib in ahk.

I tried to translate the following powershell script to CLR but it's going totally wrong:

Code: [Select all] [Download] GeSHi © Codebox Plus

import-module "path to module\Microsoft.Lync.Model.dll"
$Client = [Microsoft.Lync.Model.LyncClient]::GetClient()
$Client.state
> SigningIn


ahk code:

Code: [Select all] [Download] GeSHi © Codebox Plus

dllfile:="path to module\Microsoft.Lync.Model.dll"
CLR_Start()
asm := CLR_LoadLibrary(dllfile)
obj := CLR_CreateObject(asm, "Microsoft.Lync.Model.LyncClient")
cli := obj.GetClient()

msgbox % cli.state


Gives me an error, stating the constructor for Microsoft.Lync.Model.LyncClient could not be found. Is this even possible? Here's a link to microsoft's api reference.
I must admit that I don't know much about programming, I just found CLR and wanted to try out Lync SDK since I'm trying to enhance my lync client a little bit (which I can with vanilla ahk but only via sendinput, window detection, etc.).
lexikos
Posts: 5329
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

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

16 Sep 2016, 02:45

CLR_CreateObject is equivalent to the new operator in C# or possibly the New-Object command in PowerShell. That PowerShell script is just calling a static method.

You can't call static methods directly; you must either use another language or use Reflection. For Reflection, asm (the Assembly object) is the starting point. If you're not familiar with Reflection and don't want to research it by yourself, I would recommend creating a wrapper object in C#/VB instead, as shown in the second post in this thread.
payback87
Posts: 13
Joined: 31 Aug 2016, 01:55

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

16 Sep 2016, 03:38

Thanks for your reply, will try to look into it. A lot to learn, I have still! :)
User avatar
kczx3
Posts: 359
Joined: 06 Oct 2015, 21:39

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

12 Oct 2016, 08:24

How would one be able to reference structures and not classes/objects using this? I am playing around with xptables as well and am able to adjust the text font as I can use the following: headerFont := CLR_CreateObject(drawing, "System.Drawing.Font", "Tahoma", 20).

But I'm struggling to figure out how to adjust the font color as System.Drawing.Color is a struct.

EDIT:
It appears that the following is returning a decimal value... I get myColor to equal 255 with this. But the text color isn't changing. Does it need to be wrapped in a ComObject or SafeArray?

Code: [Select all] [Download] GeSHi © Codebox Plus

drawing := CLR_LoadLibrary("System.Drawing")
colorTranslator := CLR_CreateObject(drawing, "System.Drawing.ColorConverter")
myColor := colorTranslator.ConvertFromString("#FF0000")
lexikos
Posts: 5329
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

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

12 Oct 2016, 16:18

See Default Marshaling, and scroll down to "System.Drawing.Color".
User avatar
kczx3
Posts: 359
Joined: 06 Oct 2015, 21:39

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

12 Oct 2016, 17:19

lexikos wrote:See Default Marshaling, and scroll down to "System.Drawing.Color".

Reading through this, it seems that I should use an OLE_COLOR type which is a 32-bit integer based on my further searches.

Ole_color = red + 256 * green + 65536 * blue
Where red, green, blue are between 0-255.

This seems odd to me since the code I was using was also returning this number. I will continue to study and try some other things. Thanks.

EDIT:
Oddly enough, I found that my code (full code below with one slight modification) does actually change the row's font color, albeit getting an error in the meantime. Continuing through the error shows that the color is indeed different, though not the color I expect. I simply changed rowStyle.ForeColor := myColor to rowStyle.ForeColor := &myColor

I only thought to do this because of the error: 0x80004003 - Invalid Pointer

Code: [Select all] [Expand] [Download] GeSHi © Codebox Plus

lexikos
Posts: 5329
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

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

12 Oct 2016, 22:12

though not the color I expect.
Of course not. You're supposed to pass a color value, not an address. It's much the same as passing an address (formatted as hex) to PixelSearch or a Gui command (but the color components might be reversed).
User avatar
kczx3
Posts: 359
Joined: 06 Oct 2015, 21:39

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

13 Oct 2016, 06:29

Well, there I go trying to make things harder than it is...

Code: [Select all] [Download] GeSHi © Codebox Plus

rowStyle.ForeColor := 0x0000FF


That works as expected.

I suppose the next step would be to figure out events.
User avatar
evilC
Posts: 3150
Joined: 27 Feb 2014, 12:30

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

13 Oct 2016, 08:09

Hi, just FYI this does not work off-the-peg with AHK_H.

Replacing null with _null seems to fix this, at least for the simple example.
User avatar
evilC
Posts: 3150
Joined: 27 Feb 2014, 12:30

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

04 Mar 2017, 23:12

I had a proper play with this tonight, it's very cool.
Rather than do dynamically compiled C#, I am more interested at the moment in calling pre-compiled C# DLLs from AHK.

Attached is a C# solution with a DLL project that implements SharpDX to read joystick information via DirectInput
This will allow us to read the full 8 axes from sticks, rather than the 6 that AHK currently supports.


Demo AHK code that uses CLR to interact with the DLL:
To run, download the ZIP and extract JoystickWrapper\bin\Debug\*.dll to the same folder as the script

Code: [Select all] [Expand] [Download] GeSHi © Codebox Plus



Demo video showing input from 2 physical sticks, plus input coming from vJoy (which is being driven by UCR) so I can show it reporting Axis 8, button ID 128 and POV 4.
Image

The C# code (Project included in attached ZIP):

Code: [Select all] [Expand] [Download] GeSHi © Codebox Plus



Some questions:
I seem to be able to return an array[], but do not seem to be able to get by index (using [<index>])) or get the length, so I had to wrap it in a class and provide my own methods to do this.
I take it there is a better way to do this?

At some point I would also like to have the C# code callback to the AHK code (ie an ahk func gets called every time the joystick changes) - I take it I just need to work through the provided Events example to achieve this?
Attachments
JoystickWrapper.zip
(798.37 KiB) Downloaded 150 times
lexikos
Posts: 5329
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

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

05 Mar 2017, 01:12

Arrays are marshalled as SafeArrays by default. SafeArrays have only the methods shown in the documentation; i.e. no "length" method or property.

Code: [Select all] [Expand] [Download] GeSHi © Codebox Plus


As for working through the Events example, that would be a start...
User avatar
evilC
Posts: 3150
Joined: 27 Feb 2014, 12:30

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

05 Mar 2017, 03:50

I got the Events demo working, but I think I am going to need some kind of multi-threading in my DLL.

However, when I try to extend the sample code to use a thread, I only get 1 callback then it stops:
Does anyone know what I am doing wrong?

Code: [Select all] [Expand] [Download] GeSHi © Codebox Plus

lexikos
Posts: 5329
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

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

05 Mar 2017, 04:25

What you're doing wrong is multi-threading. It is not safe to call script functions on any thread other than the program's main thread.
User avatar
evilC
Posts: 3150
Joined: 27 Feb 2014, 12:30

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

05 Mar 2017, 04:33

Is there another way I can have a loop going but not lock up the main thread?
ie have a number of psuedo-threads or something polling sticks, but still allow calls into the main thread to facilitate turning on/off polling?

Can I use SetTimer?
lexikos
Posts: 5329
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

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

05 Mar 2017, 05:28

You can do whatever you want in C#.

If you need to call a script function, do it from the right thread. How you do that is up to you. I would suggest using PostMessage and OnMessage, since you're likely already familiar with them.

The Timer class you linked appears to have no connection to the SetTimer command or Win32 function. I'm not familiar with its use.

FYI, I haven't really used .NET at all in the last decade except to develop this library, and I've barely used the library except to test it.
User avatar
evilC
Posts: 3150
Joined: 27 Feb 2014, 12:30

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

05 Mar 2017, 05:36

OK, I think I vaguely get what you are saying.

So I can have worker threads running in the DLL, but in order for the callbacks to work, I need to go via the main DLL thread

ie worker thread wants to fire callback, so it communicates to the main DLL thread, and the main DLL thread fires the callback to the AHK script.
lexikos
Posts: 5329
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

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

05 Mar 2017, 06:14

Using LresultFromObject and ObjectFromLresult, it's possible to pass an object pointer between processes or threads, automatically giving you a proxy object when necessary. A proxy object does nothing more than forward interface calls back to the original object on its original thread, so is safe to use from outside the main thread. I figured that these functions would be easy enough to use from C#, but it turns out they were completely unnecessary. .NET takes care of it automatically, presumably because it can detect that COM was initialised on the main thread as a "single threaded apartment".

This requires .NET 4.0 (at least, for dynamic):

Code: [Select all] [Expand] [Download] GeSHi © Codebox Plus


Of course, while handler.Handle() is executing after being called from the new thread, both threads are tied up.

Return to “Scripts and Functions”

Who is online

Users browsing this forum: arcticir and 19 guests