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

Post your working scripts, libraries and tools for AHK v1.1 and older
metaprogram
Posts: 4
Joined: 16 Dec 2020, 16:31

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

Post by metaprogram » 16 Dec 2020, 17:25

I think there is a bug in this script when returning arrays of length 0. For example:

Code: Select all

    ; Return a string[] type
    cSharp =
    (
        class ArrayReturnValueTest
        {
            public string[] Foo()
            {
                return new string[0]{};
            }
        }
    )

    obj := CLR_CreateObject( CLR_CompileC#( cSharp ), "ArrayReturnValueTest")
    result := obj.Foo()
    For found in result
    {
        
    }
complains about an invalid memory read/write. Anyone know how to fix this?
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

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

Post by lexikos » 30 Jan 2021, 02:05

The script just calls the compiler and instantiates the class. It is not responsible for marshaling the method call or return value, or implementing the method or enumeration (for-loop).

The bug is with enumeration of an empty SafeArray by AutoHotkey, and can potentially be reproduced by for a in ComObjArray(0x8, 0) { ... }.
serzh82saratov
Posts: 137
Joined: 01 Jul 2017, 03:04

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

Post by serzh82saratov » 30 Jan 2021, 11:00

Hello!
Is it possible using the CLR to create a Windows.ApplicationModel.DataTransfer object, and then use it in AutoHotkey?
Here is a sample code, not convenient and difficult to use for each DllCall method (NumGet (NumGet (.
Would like something like here JavaScript is easy to use an object.

Code: Select all

; Author - teadrinker
; http://forum.script-coding.com/viewtopic.php?pid=145546#p145546

; puts the second item from the Windows 10 clipboard history into the Clipboard and returns a success status
MsgBox, % (new ClipboardHistory).PutHistoryItemIntoClipboard(2)

; get the text of the elements of the clipboard history by index
ClipHist := new ClipboardHistory
Loop % ClipHist.Count
   MsgBox,, Item %A_Index%, % ClipHist.GetHistoryItemText(A_Index), .7

class ClipboardHistory
{
; https://is.gd/bYyogJ ; Clipboard Class (MSDN)
; https://is.gd/2z2Y9G ; Windows.ApplicationModel.DataTransfer.0.h (GitHub)
; https://is.gd/T4Lb7b ; asyncinfo.h (GitHub)
   __New() {
      static IID_IClipboardStatics2 := "{D2AC1B6A-D29F-554B-B303-F0452345FE02}"
      if !(A_OSVersion ~= "^\d") {
         MsgBox, This class requires Windows 10 or later!
         Return
      }
      riid := CLSIDFromString(IID_IClipboardStatics2, _)

      WinStr := new WindowsString("Windows.ApplicationModel.DataTransfer.Clipboard")
      WinStr.CreateInterface(riid, pIClipboardStatics2)
      WinStr := ""

      this.ClipboardStatics2 := new IClipboardStatics2( pIClipboardStatics2 )
   }
   
   __Delete() {
      this.ClipboardStatics2 := ""
   }
   
   IsHistoryEnabled[] {
      get {
         Return this.ClipboardStatics2.IsHistoryEnabled
      }
   }
   
   Count[] {
      get {
         Return this._GetClipboardHistoryItems(ReadOnlyList)
      }
   }
   
   ClearHistory() {
      Return this.ClipboardStatics2.ClearHistory()
   }
   
   GetHistoryItemText(index) { ; 1 based
      if !pIClipboardHistoryItem := this._GetClipboardHistoryItemByIndex(index)
         Return
      ClipboardHistoryItem := new IClipboardHistoryItem( pIClipboardHistoryItem )
      pIDataPackageView := ClipboardHistoryItem.Content
      DataPackageView := new IDataPackageView( pIDataPackageView )
      pIReadOnlyList := DataPackageView.AvailableFormats
      ReadOnlyList := new IReadOnlyList( pIReadOnlyList )
      Loop % ReadOnlyList.Count
         if StrGet(ReadOnlyList.Item[A_Index - 1] + 20 + A_PtrSize, "UTF-16") = "Text" && textFound := true
            break
      if !textFound
         Return
      DataPackageView.GetTextAsync(pIAsyncOperation)
      pString := this._AsyncOperationGetResults(pIAsyncOperation)
      Return StrGet(pString + 20 + A_PtrSize, "UTF-16")
   }
   
   PutHistoryItemIntoClipboard(index) { ; 1 based
      static SetHistoryItemAsContentStatus := ["Success", "AccessDenied", "ItemDeleted"]
      if !pIClipboardHistoryItem := this._GetClipboardHistoryItemByIndex(index)
         Return
      ClipboardHistoryItem := new IClipboardHistoryItem( pIClipboardHistoryItem )
      status := this.ClipboardStatics2.SetHistoryItemAsContent( ClipboardHistoryItem.ptr )
      Return SetHistoryItemAsContentStatus[ status + 1 ]
   }
   
   _GetClipboardHistoryItemByIndex(index) { ; 1 based
      count := this._GetClipboardHistoryItems(ReadOnlyList)
      if (count < index) {
         MsgBox, 48, % " ", Index "%index%" exceeds items count!
         Return
      }
      Return pIClipboardHistoryItem := ReadOnlyList.Item[index - 1]
   }
   
   _GetClipboardHistoryItems(ByRef ReadOnlyList) {
      this.ClipboardStatics2.GetHistoryItemsAsync( pIAsyncOperation )
      pIClipboardHistoryItemsResult := this._AsyncOperationGetResults(pIAsyncOperation)
      ClipboardHistoryItemsResult := new IClipboardHistoryItemsResult( pIClipboardHistoryItemsResult )
      pIReadOnlyList := ClipboardHistoryItemsResult.Items
      ReadOnlyList := new IReadOnlyList( pIReadOnlyList )
      Return ReadOnlyList.Count
   }
   
   _AsyncOperationGetResults(pIAsyncOperation) {
      static AsyncStatus  := ["Started", "Completed", "Canceled", "Error"]
      AsyncOperation := new IAsyncOperation( pIAsyncOperation )
      AsyncOperation.QueryIAsyncInfo(pIAsyncInfo)
      AsyncInfo := new IAsyncInfo( pIAsyncInfo )
      Loop {
         Sleep, 10
         status := AsyncStatus[ AsyncInfo.Status + 1 ]
      } until status != "Started" || status = ""
      if (status != "Completed")
         throw "AsyncInfo error, status: """ . status . """"
      AsyncOperation.GetResults( pResult )
      Return pResult
   }
}

class IClipboardStatics2 extends _InterfaceBase
{
   GetHistoryItemsAsync(ByRef pIAsyncOperation) {
      hr := DllCall(this.VTable(6), "Ptr", this.ptr, "UIntP", pIAsyncOperation)
      this.IsError(A_ThisFunc, hr)
   }
   ClearHistory() {
      hr := DllCall(this.VTable(7), "Ptr", this.ptr, "UIntP", res)
      this.IsError(A_ThisFunc, hr)
      Return res
   }
   SetHistoryItemAsContent(pIClipboardHistoryItem) {
      hr := DllCall(this.VTable(9), "Ptr", this.ptr, "Ptr", pIClipboardHistoryItem, "UIntP", res)
      this.IsError(A_ThisFunc, hr)
      Return res
   }
   IsHistoryEnabled[] {
      get {
         hr := DllCall(this.VTable(10), "Ptr", this.ptr, "UIntP", res)
         this.IsError(A_ThisFunc, hr)
         Return res
      }
   }
}

class IClipboardHistoryItemsResult extends _InterfaceBase
{
   Items[] {
      get {
         hr := DllCall(this.VTable(7), "Ptr", this.ptr, "PtrP", pIReadOnlyList)
         this.IsError(A_ThisFunc, hr)
         Return pIReadOnlyList
      }
   }
}

class IClipboardHistoryItem extends _InterfaceBase
{
   Content[] {
      get {
         hr := DllCall(this.VTable(8), "Ptr", this.ptr, "PtrP", pIDataPackageView)
         this.IsError(A_ThisFunc, hr)
         Return pIDataPackageView
      }
   }
}

class IDataPackageView extends _InterfaceBase
{
   AvailableFormats[] {
      get {
         hr := DllCall(this.VTable(9), "Ptr", this.ptr, "PtrP", pIReadOnlyList)
         this.IsError(A_ThisFunc, hr)
         Return pIReadOnlyList
      }
   }
   GetTextAsync(ByRef pIAsyncOperation) {
      hr := DllCall(this.VTable(12), "Ptr", this.ptr, "UIntP", pIAsyncOperation)
      this.IsError(A_ThisFunc, hr)
   }
}

class IReadOnlyList extends _InterfaceBase
{
   Item[index] {
      get {
         hr := DllCall(this.VTable(6), "Ptr", this.ptr, "Int", index, "PtrP", pItem)
         this.IsError(A_ThisFunc, hr)
         Return pItem
      }
   }
   Count[] {
      get {
         hr := DllCall(this.VTable(7), "Ptr", this.ptr, "UIntP", count)
         this.IsError(A_ThisFunc, hr)
         Return count
      }
   }
}

class IAsyncOperation extends _InterfaceBase
{
   QueryIAsyncInfo(ByRef pIAsyncInfo) {
      static IID_IAsyncInfo := "{00000036-0000-0000-C000-000000000046}"
      pIAsyncInfo := ComObjQuery(this.ptr, IID_IAsyncInfo)
   }
   GetResults(ByRef pResult) {
      hr := DllCall(this.VTable(8), "Ptr", this.ptr, "PtrP", pResult)
      this.IsError(A_ThisFunc, hr)
   }
}

class IAsyncInfo extends _InterfaceBase
{
   Status[] {
      get {
         hr := DllCall(this.VTable(7), "Ptr", this.ptr, "UIntP", status)
         this.IsError(A_ThisFunc, hr)
         Return status
      }
   }
}

class _InterfaceBase {
   __New(ptr) {
      this.ptr := ptr
   }
   __Delete() {
      ObjRelease(this.ptr)
   }
   VTable(idx) {
      Return NumGet(NumGet(this.ptr + 0) + A_PtrSize*idx)
   }
   IsError(method, result, exc := true) {
      if (result = 0)
         Return 0
      error := StrReplace(method, ".", "::") . " failed.`nResult: "
                              . ( result = "" ? "No result" : SysError(Format("{:#x}", result & 0xFFFFFFFF)) )
                              . "`nErrorLevel: " . ErrorLevel
      if !exc
         Return error
      throw error
   }
}

class WindowsString {
   __New(string, isHandle := false) {
      if isHandle
         this.hString := string
      else {
         DllCall("Combase\WindowsCreateString", "WStr", string, "UInt", StrLen(string), "PtrP", hString)
         this.hString := hString
      }
   }
   __Delete() {
      DllCall("Combase\WindowsDeleteString", "Ptr", this.hString)
   }
   Get() {
      pBuff := DllCall("Combase\WindowsGetStringRawBuffer", "Ptr", this.hString, "UIntP", len, "Ptr")
      Return StrGet(pBuff, len, "UTF-16")
   }
   CreateInterface(riid, ByRef pInterface) {
      hr := DllCall("Combase\RoGetActivationFactory", "Ptr", this.hString, "Ptr", riid, "PtrP", pInterface)
      if (hr != 0)
         throw SysError(hr)
   }
}

CLSIDFromString(IID, ByRef CLSID) {
   VarSetCapacity(CLSID, 16, 0)
   if hr := DllCall("ole32\CLSIDFromString", "WStr", IID, "Ptr", &CLSID, "UInt")
      throw "CLSIDFromString failed. Error: " . Format("{:#x}", hr)
   Return &CLSID
}

SysError(ErrorNum = "")
{ 
   static flag := (FORMAT_MESSAGE_ALLOCATE_BUFFER := 0x100) | (FORMAT_MESSAGE_FROM_SYSTEM := 0x1000)
   (ErrorNum = "" && ErrorNum := A_LastError)
   DllCall("FormatMessage", "UInt", flag, "UInt", 0, "UInt", ErrorNum, "UInt", 0, "PtrP", pBuff, "UInt", 512, "Str", "")
   Return (str := StrGet(pBuff)) ? str : ErrorNum
}
serzh82saratov
Posts: 137
Joined: 01 Jul 2017, 03:04

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

Post by serzh82saratov » 30 Jan 2021, 11:57

I try so, error.
Spoiler
Last edited by serzh82saratov on 30 Jan 2021, 13:45, edited 1 time in total.
serzh82saratov
Posts: 137
Joined: 01 Jul 2017, 03:04

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

Post by serzh82saratov » 30 Jan 2021, 13:44

More precisely, something like this. The point is to get the root object and manipulate it from AutoHotkey.
This is an approximate VB code, maybe you suggest C # and it will be better.

Code: Select all

vb =
( 
   Imports System
   Imports Windows
   Class Foo
      Function GetWA() as Object
         Return Windows.ApplicationModel
     End Function
   End Class
)
asm := CLR_CompileVB(vb, "System.dll | Windows.dll")
Foo := CLR_CreateObject(asm, "Foo")
WA := Foo.GetWA()
WA.DataTransfer.Clipboard.clear()
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

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

Post by lexikos » 30 Jan 2021, 19:29

You can do whatever you want in C# or VB. This script is just for loading the CLR, invoking the C# and VB compilers and creating instances of classes directly. Once you have an instance, you use it via .NET COM interop (as in, the COM interfaces provided by the library or the CLR itself) and AutoHotkey's COM support, which are not part of this script.
serzh82saratov
Posts: 137
Joined: 01 Jul 2017, 03:04

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

Post by serzh82saratov » 30 Jan 2021, 19:49

Yes, but it is with Windows.ApplicationModel that it fails.
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

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

Post by lexikos » 31 Jan 2021, 00:48

What's your point? Mine is that the failure is outside the scope of this script.
nadure
Posts: 22
Joined: 26 Mar 2021, 23:02
Location: Korea
Contact:

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

Post by nadure » 27 Mar 2021, 06:08

Hi! :D
This is first write for question!
How to return the c# Dictionary object.

Below, this is example code. using CLR lib.


Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

;~ IDictionary List
;~ {F31091E6-B0A8-11D6-B6FC-005056C00008}
;~ {6A6841DF-3287-3D87-8060-CE0B4C77D2A1}
;~ {42C642C1-97E1-11CF-978F-00A02463E06F}

#Include CLR.ahk

ICollection_IID := "{DE8DB6F8-D101-3A92-8D1C-E72E5F10E992}"
IDictionary_IID_v1 := "{F31091E6-B0A8-11D6-B6FC-005056C00008}"
IDictionary_IID_v2 := "{42C642C1-97E1-11CF-978F-00A02463E06F}"
IDictionary_IID_v3 := "{6A6841DF-3287-3D87-8060-CE0B4C77D2A1}"

IList_IID := "{7BCFA00F-F764-3113-9140-3BBD127A96BB}"
Dictionary_IID := "{000209AD-0000-0000-C000-000000000046}"

IDispatch := "{00020400-0000-0000-C000-000000000046}"
IUnknown := "{00000000-0000-0000-C000-000000000046}"

IID_IProvideClassInfo := "{B196B283-BAB4-101A-B69C-00AA00341D07}"


vc =
( 
	using System;
	using System.Collections.Generic;
	
	class DictionaryReturnValueTest
	{
		public Dictionary<string, string> ReturningDictTest()
        {
            var dict = new Dictionary<string, string>();
            dict.Add("who", "nadure");
            dict.Add("is", "C_Sharp");
            dict.Add("tis", "t_Sharp");
            dict.Add("dis", "d_Sharp");
            return dict;
        }
		
		public string ReturningTest()
		{
			string str = "Hello";
			return str;
		}
	}
)

dv := CLR_CreateObject(CLR_CompileC#(vc, "System.dll | System.Windows.Forms.dll | System.Collections.dll"), "DictionaryReturnValueTest")


value := dv.ReturningDictTest()

ICollection := ComObject(9, ComObjQuery(value, ICollection_IID), 1)
IDictionary := ComObject(0x2000, ComObjQuery(ICollection, IDictionary_IID_v3), 1)

;~ res := ComObjQuery(ICollection, IDictionary_IID_v3)


;~ Msgbox,% res
;~ if !(res)
;~ {
	;~ Msgbox, Error
;~ }


Msgbox,% IDictionary["who"]

return


f2::
ExitApp



I tried using IID but not works. :evil:

Is it possible?
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

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

Post by lexikos » 27 Mar 2021, 22:14

Isn't just value := dv.ReturningDictTest() sufficient?
nadure
Posts: 22
Joined: 26 Mar 2021, 23:02
Location: Korea
Contact:

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

Post by nadure » 28 Mar 2021, 22:34

lexikos wrote:
27 Mar 2021, 22:14
Isn't just value := dv.ReturningDictTest() sufficient?
um.. this is not works for the test.

Code: Select all

Msgbox,% value["who"]
Is this a SafeArray?

if the value is SafeArray, what is the method for pick up the value from the SafeArray?

In other comment,
https://www.autohotkey.com/boards/viewtopic.php?style=7&f=6&t=4633&p=292050&hilit=IList#p292050

Using ComobjQuery and Comobject for picking up value from array(actually IList). so i had done similar. but not works..

Would you like to give me some ideas?
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

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

Post by lexikos » 30 Mar 2021, 03:42

AutoHotkey works with .NET objects by querying for the _Object interface, which extends IDispatch. Querying for IDispatch only works if the class has appropriate attributes (i.e. it's designed to be used by COM clients), whereas querying for _Object always returns that interface. It generally works, but probably isn't officially supported by Microsoft.

It looks like the dispatch implementation for generic types through the _Object interface is broken or absent. When we attempt to call IDispatch::GetIDsOfNames, something within the implementation (in clr.dll) tries to dereference a null pointer, causing an access violation. I confirmed this with a simple Test<T> class with one field T Value;, instantiated with Test<string>. The equivalent non-generic class worked fine.

I suppose that dynamic dispatch of calls from COM clients to generic types just isn't implemented, because COM fundamentally doesn't support generics.

Some notes regarding your attempts:
  • ComObject(9, ptr) is only valid if ptr is for IDispatch or an interface derived from IDispatch. ICollection does not derive from IDispatch.
  • If the interface does not derive from IDispatch, you cannot invoke it dynamically. You may invoke it by manually by retrieving the function address from the interface's virtual function table with NumGet and passing it to DllCall (for example, see ITaskbarList). You must specify the correct offset in the function table, and the correct parameter types.
    It would be far easier to use a non-generic class which will work with IDispatch automatically.
  • Interfaces and SAFEARRAYs are completely different. You cannot reinterpret an interface pointer as a pointer to a SAFEARRAY, such as by passing it to ComObject(0x2000 ...).
  • Dictionaries and SAFEARRAYs are not equivalent. SAFEARRAY is equivalent to a plain array.
  • If you have a pointer to a SAFEARRAY, when you wrap it with ComObject() you must specify the base type of the array. For example, VT_ARRAY|VT_BSTR (0x2008) is an array of strings. You will get a SAFEARRAY of this type when you return a string[] from C#.

Changing the return type to object or a non-generic interface will not help if the object is still a generic type, as it is the implementation of the object/class that matters. For instance, (IDictionary)dict is still the same object as dict, so (_Object)(IDictionary)dict == (_Object)dict.

Querying for a non-generic interface should work (I'm not sure that you can query for a generic interface anyway, as it might never have an IID), but you still have to use the interface correctly. ICollection and IDictionary could only be used through DllCall, and working out the order of methods in the vtable can be a pain so I'm going to suggest that you just avoid using generic classes (for objects that you return to the script).
nadure
Posts: 22
Joined: 26 Mar 2021, 23:02
Location: Korea
Contact:

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

Post by nadure » 30 Mar 2021, 08:51

Thanks for very detailed explanation.
As your mention, this is very hard way to work on.
but I'm so touching very things. i'll understand little more, and use it another project.


Have a good day!
Last edited by lexikos on 30 Mar 2021, 21:40, edited 1 time in total.
Reason: Removed large, redundant quote
hylotropy
Posts: 14
Joined: 28 Jan 2021, 23:01

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

Post by hylotropy » 18 Apr 2021, 23:41

@lexikos please help, I tried to translate the following powershell script to autohotkey but got an error 0x80131509.

ILSpy : https://imgur.com/a/5jtXOxG

powershell

Code: Select all

Add-Type -Path "C:\Users\Admin\Desktop\OpenHardwareMonitor\OpenHardwareMonitorLib.dll"
$Comp = New-Object -TypeName OpenHardwareMonitor.Hardware.Computer
$Comp.Open()
$Comp.CPUEnabled = $true
$Comp.Hardware[0].HardwareType    #return "Cpu"

autohotkey

Code: Select all

SetWorkingDir %A_ScriptDir%  ;
OpenHardwareMonitorLibPath:=A_ScriptDir "\OpenHardwareMonitorLib.dll"
asm := CLR_LoadLibrary(OpenHardwareMonitorLibPath)
computer := CLR_CreateObject(asm, "OpenHardwareMonitor.Hardware.Computer")
computer.Open()
computer.CpuEnabled  :=computer.HDDEnabled := computer.RAMEnabled := 1 
Hardwares:= computer.Hardware
msgbox,%  ComObjType(Hardwares[0])  ;return  9
msgbox,%  ComObjType(Hardwares[1])  ;return  9
msgbox,%  ComObjType(Hardwares[2])  ;return  9
msgbox,%  ComObjType(Hardwares[0].HardwareType)  ; Error:  0x80131509 -  Specifically: HardwareType
Image
Attachments
OpenHardwareMonitorLib.zip
(119.34 KiB) Downloaded 108 times
hylotropy
Posts: 14
Joined: 28 Jan 2021, 23:01

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

Post by hylotropy » 19 Apr 2021, 06:25

What is the difference between clr.ahk and pythonnet? It is easy to use OpenHardwareMonitorLib.dll in vb, powershell, and even python (pythonnet), I don't understand why it is so difficult to use OpenHardwareMonitorLib.dll in autohotkey.

Code: Select all

import clr
clr.AddReference("c:/OpenHardwareMonitorLib.dll") 
from OpenHardwareMonitor.Hardware import Computer 
 
computer_tmp = Computer() 
computer_tmp.CPUEnabled = True 
computer_tmp.Open()
print (computer_tmp.Hardware[0].HardwareType)  # CPU
User avatar
dd900
Posts: 121
Joined: 27 Oct 2013, 16:03

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

Post by dd900 » 08 May 2021, 15:43

@lexikos

typeofAssembly.InvokeMember_3("LoadFrom", 0x158, null, null, args)

I'm having trouble trying to figure out bitwise combinations still. Please don't refer me to jeeswg's mathematics tutorial. While it is an amazing resource, I cannot just read an explanation and look at arbitrary numbers and be expected to understand. That's not how my brain works. I need a real world example and the code above is perfect. How did you come up with 0x158? I know its a bitwise combo of BindingFlags. What I don't know is what Flags you are combining (and how) you got the desired output. I'm assuming you are using "public" and "static" flags and....?

How would I go about calling the following with CLR? Does return value matter?

Code: Select all

public static class foo
{
	public static string StrMethod() {
		//do stuff
	}
	
	public static void VoidMethod() {
		//do stuff
	}
}
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

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

Post by lexikos » 28 Aug 2021, 01:48

I have uploaded CLR.ahk to GitHub, along with an updated version for AutoHotkey v2.0-beta.1.

https://github.com/Lexikos/CLR.ahk
burque505
Posts: 1734
Joined: 22 Jan 2017, 19:37

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

Post by burque505 » 29 Aug 2021, 09:19

Thank you very much!
xroot
Posts: 40
Joined: 21 Jun 2019, 08:45

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

Post by xroot » 01 Sep 2021, 08:33

Fooling with CLR v2.0-beta.1

My C# code works just fine.

Added this code to CLR AutoHotkey v2.0-beta.1 #include:

Code: Select all

CLR_CompileJS(Code, References:="", AppDomain:=0, FileName:="", CompilerOptions:="")
{
	return CLR_CompileAssembly(Code, References, "System", "Microsoft.JScript.JScriptCodeProvider", AppDomain, FileName, CompilerOptions)
}                                                           
The idea for JScript from here:
https://docs.microsoft.com/en-us/dotnet/api/system.codedom.compiler.codedomprovider?view=netframework-4.8

Get this ERROR message:
Error in #include file "CLR.ahk":
This value of type "String" has no method named "CreateCompiler".

The Line "codeProvider := asmProvider.CreateInstance(ProviderType)" failed, "codeProvider" is "string" instead of "codeDomProvider" object.

Any clue on what is needed for "Microsoft.JScript.JScriptCodeProvider"?

Thanks
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

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

Post by lexikos » 02 Sep 2021, 03:36

You must specify the correct assembly. JScriptCodeProvider is in Microsoft.JScript.dll, not System.dll.

As for actually using JScript.net, don't ask me. Note that it is not JavaScript, and in particular, is not modern JavaScript.
Post Reply

Return to “Scripts and Functions (v1)”