Jump to content

Using .NET libary with AutoIt, possible?


Recommended Posts

If I call CLRCreateInstance in this way it leads to an immediate crash (0xC0000005, STATUS_ACCESS_VIOLATION):

Local $aRet = DllCall( "MSCorEE.DLL", "long", "CLRCreateInstance", "struct*", $tCLSID_CLRMetaHost, _
                       "struct*", $tIID_ICLRMetaHost, "ptr*", 0 )

A couple of weeks ago I did a few tests with CLR.ahk from our AutoHotkey friends. They are using the function CorBindToRuntimeEx also implemented in MSCorEE.DLL. This function works in AutoIt in this way:

Local $aRet = DllCall( "MSCorEE.dll", "long", "CorBindToRuntimeEx", "wstr", $sVersion, "ptr", NULL, "dword", 0, _
                       "struct*", $tCLSID_CorRuntimeHost, "struct*", $tIID_ICorRuntimeHost, "ptr*", 0 )

I don't know why CLRCreateInstance leads to a crash. It could be interesting to see if CLRCreateInstance is working in AutoHotkey.

A quick way to get around the problem and be able to move on is to call CLRCreateInstance through some C++ code in a DLL file. Whether you can get a pointer in this way which can be used in AutoIt, you simply have to test.

Link to comment
Share on other sites

This work for me @LarsJ

 

Global Const $S_OK = 0
Global $tCLSID_CLRMetaHost = _WinAPI_CLSIDFromString("{9280188d-0e8e-4867-b30c-7fa83884e8de}")
Global $tIID_ICLRMetaHost = _WinAPI_CLSIDFromString("{D332DB9E-B9B3-4125-8207-A14884F53216}")



Local $aRet = DllCall("MSCorEE.DLL", "long", "CLRCreateInstance", "struct*", $tCLSID_CLRMetaHost, _
        "struct*", $tIID_ICLRMetaHost, "ptr*", 0)

If $aRet[0] = $S_OK Then
    Local $pClrHost = $aRet[3]
    ConsoleWrite("$pClrHost: " & $pClrHost & @CRLF)
EndIf
Func _WinAPI_CLSIDFromString($sGUID)
    $tGUID = DllStructCreate('ulong Data1;ushort Data2;ushort Data3;byte Data4[8]')
    $iRet = DllCall('ole32.dll', 'uint', 'CLSIDFromString', 'wstr', $sGUID, 'ptr', DllStructGetPtr($tGUID))
    If (@error) Or ($iRet[0]) Then
        Return SetError(@error, @extended, 0)
    EndIf
    Return $tGUID
EndFunc   ;==>_WinAPI_CLSIDFromString

Saludos

Link to comment
Share on other sites

Danyfirex, Excellent. Your code also works for me.

My code was a little too short. I had only:

$tCLSID_CLRMetaHost = "{9280188D-0E8E-4867-B30C-7FA83884E8DE}"
$tIID_ICLRMetaHost = "{D332DB9E-B9B3-4125-8207-A14884F53216}"

 

ptrex, Now you have the pointer for ICLRMetaHost and you should be able to create the object.

And it's this C++ code in the link by junkew you are trying to translate into AutoIt?

Link to comment
Share on other sites

Link to comment
Share on other sites

I got some free time and traslated the C++ code to AutoIt.  

I've attached a sample.

 

AutoIt Code

;~ #AutoIt3Wrapper_UseX64=y

Global Const $S_OK = 0

;I'm lazy for that you'll see ptr type in most of interfaces parameters... :P
#Region Interfaces
Global Const $sTagCLRMetaHost = "GetRuntime hresult(wstr;struct*;ptr);" & _
        "GetVersionFromFile hresult(ptr;ptr;ptr);" & _
        "EnumerateInstalledRuntimes hresult(ptr)" & _
        "EnumerateLoadedRuntimes hresult(ptr;ptr)" & _
        "RequestRuntimeLoadedNotification hresult(ptr,ptr,ptr)" & _
        "QueryLegacyV2RuntimeBinding hresult(ptr;ptr)" & _
        "ExitProcess hresult(int)"

Global Const $sTagCLRRuntimeInfo = "GetVersionString hresult(ptr;ptr);" & _
        "GetRuntimeDirectory hresult(ptr;ptr);" & _
        "IsLoaded hresult(ptr;ptr);" & _
        "LoadErrorString hresult(ptr;ptr;ptr;ptr);" & _
        "LoadLibrary hresult(ptr;ptr);" & _
        "GetProcAddress hresult(ptr;ptr);" & _
        "GetInterface hresult(ptr;ptr;ptr);" & _
        "IsLoadable hresult(Bool*);" & _
        "SetDefaultStartupFlags hresult(ptr;ptr);" & _
        "GetDefaultStartupFlags hresult(ptr;ptr;ptr);" & _
        "BindAsLegacyV2Runtime hresult();" & _
        "IsStarted hresult(ptr;ptr);"

Global Const $sTagRuntimeHost = "Start hresult();Stop hresult();SetHostControl hresult(ptr);GetCLRControl hresult(ptr);" & _
        "UnloadAppDomain hresult(ptr;ptr);ExecuteInAppDomain hresult(ptr;ptr;ptr);GetCurrentAppDomainId hresult(ptr);" & _
        "ExecuteApplication hresult(ptr;ptr;ptr;ptr;ptr;ptr);" & _
        "ExecuteInDefaultAppDomain hresult(wstr;wstr;wstr;wstr;ptr*);"
#EndRegion Interfaces


#Region CLSID & IID
Global Const $sCLSID_CLRMetaHost = "{9280188d-0e8e-4867-b30c-7fa83884e8de}"
Global Const $sIID_ICLRMetaHost = "{d332db9e-b9b3-4125-8207-a14884f53216}"
Global Const $sIID_ICLRRuntimeInfo = "{BD39D1D2-BA2F-486a-89B0-B4B0CB466891}"
Global Const $sCLSID_CLRRuntimeHost = "{90F1A06E-7712-4762-86B5-7A5EBA6BDB02}"
Global Const $sIID_ICLRRuntimeHost = "{90F1A06C-7712-4762-86B5-7A5EBA6BDB02}"

Global $tCLSID_CLRMetaHost = _WinAPI_CLSIDFromString($sCLSID_CLRMetaHost)
Global $tIID_ICLRMetaHost = _WinAPI_CLSIDFromString($sIID_ICLRMetaHost)
Global $tIID_ICLRRuntimeInfo = _WinAPI_CLSIDFromString($sIID_ICLRRuntimeInfo)
Global $tCLSID_CLRRuntimeHost = _WinAPI_CLSIDFromString($sCLSID_CLRRuntimeHost)
Global $tIID_ICLRRuntimeHost = _WinAPI_CLSIDFromString($sIID_ICLRRuntimeHost)
#EndRegion CLSID & IID

Local $hMSCorEE = DllOpen("MSCorEE.DLL")
;get ClrHost
Local $aRet = DllCall($hMSCorEE, "long", "CLRCreateInstance", "struct*", $tCLSID_CLRMetaHost, _
        "struct*", $tIID_ICLRMetaHost, "ptr*", 0)



If $aRet[0] = $S_OK Then
    Local $pClrHost = $aRet[3]
    Local $oClrHost = ObjCreateInterface($pClrHost, $sIID_ICLRMetaHost, $sTagCLRMetaHost)
    ConsoleWrite(">oClrHost: " & IsObj($oClrHost) & @CRLF)

    Local $sNETFrameworkVersion = "v4.0.30319"
    Local $tRunInfo = DllStructCreate("ptr")
    $oClrHost.GetRuntime($sNETFrameworkVersion, $tIID_ICLRRuntimeInfo, DllStructGetPtr($tRunInfo))
    Local $pRunInfo = DllStructGetData($tRunInfo, 1)
    ConsoleWrite(">pRunInfo: " & $pRunInfo & @CRLF)

    Local $oRunInfo = ObjCreateInterface($pRunInfo, $sIID_ICLRRuntimeInfo, $sTagCLRRuntimeInfo)
    ConsoleWrite(">oRunInfo: " & IsObj($oRunInfo)  & @CRLF)
    Local $isIsLoadable = 0
    $oRunInfo.IsLoadable($isIsLoadable)
    ConsoleWrite(">IsLoadable: " & $isIsLoadable & @CRLF)


    If $isIsLoadable Then
        Local $tRuntimeHost = DllStructCreate("ptr")
        $oRunInfo.GetInterface(DllStructGetPtr($tCLSID_CLRRuntimeHost), DllStructGetPtr($tIID_ICLRRuntimeHost), DllStructGetPtr($tRuntimeHost))
        Local $pRuntimeHost = DllStructGetData($tRuntimeHost, 1)
        ConsoleWrite(">pRuntimeHost: " & $pRuntimeHost & @CRLF)
        Local $oRuntimeHost = ObjCreateInterface($pRuntimeHost, $sIID_ICLRRuntimeHost, $sTagRuntimeHost)
        ConsoleWrite(">oRuntimeHost" & IsObj($oRuntimeHost)  & @CRLF)


        Local $iRet = 0
        $oRuntimeHost.Start()
        $oRuntimeHost.ExecuteInDefaultAppDomain(@ScriptDir & "\C#Library.dll", "ClassLibraryDemo.ClassDemo", "NetMsgBox", "AutoIt Rocks!!! " & @CRLF & "Danyfirex does too lol!!!", $iRet)
        ConsoleWrite(">Ret: " & $iRet & @CRLF)

    EndIf

EndIf

DllClose($hMSCorEE) ;free


Func _WinAPI_CLSIDFromString($sGUID)
    $tGUID = DllStructCreate('ulong Data1;ushort Data2;ushort Data3;byte Data4[8]')
    $iRet = DllCall('ole32.dll', 'uint', 'CLSIDFromString', 'wstr', $sGUID, 'ptr', DllStructGetPtr($tGUID))
    If (@error) Or ($iRet[0]) Then
        Return SetError(@error, @extended, 0)
    EndIf
    Return $tGUID
EndFunc   ;==>_WinAPI_CLSIDFromString

 

Super libary source code

using System.Windows.Forms;

namespace ClassLibraryDemo
{
    public class ClassDemo
    {
        public static int NetMsgBox(string message)
        {
            MessageBox.Show(message);
            return 1;
        }
    }
}

 

 

Demo

CLRAutoIt.zip

 

Saludos

Link to comment
Share on other sites

@Danyfirex

This is really great news :) ... I will test it later today...

If all works fine it opens a totally new world for the community ...

Thanks a lot for the efforts so far ...

ptrex

Ps : I propose to move this post to the Example section.

Or even create a new section in the forum :yawn:

Link to comment
Share on other sites

nice work and it rocks here also ;-)

Hard time to understand how to deal in AutoIt with all this pointer logic which is to me at least more difficult then it is in c++ or c# itself

Any reference / guide on this DLL thing from within AutoIt? Tried to get just a simple GetVersionString to work without a result (0,0 is printed). offcourse reading manual/help file on all DLL* functions

;~  HRESULT GetVersionString(
;~     [out, size_is(*pcchBuffer)] LPWSTR pwzBuffer,
;~     [in, out]  DWORD *pcchBuffer);
    ; Assign some space to get data back
    Local $mySTRUCT = DllStructCreate("wchar[16] pwzBuffer; dword pcchBuffer")
    dllstructsetdata($myStruct,"pcchBuffer",16) ;~ probably 32 should be given
    $oRunInfo.GetVersionString(dllstructgetptr($myStruct,"pwzBuffer"), dllstructgetptr($myStruct,"pcchBuffer"))
    ConsoleWrite(">Version: " & dllstructgetdata($myStruct,"pwzBuffer") & dllstructgetdata($myStruct,"pcchBuffer") & @CRLF)

 

Edited by junkew
Link to comment
Share on other sites

@junkew Try this.

 

;~ #AutoIt3Wrapper_UseX64=y

Global Const $S_OK = 0

;I'm lazy for that you'll see ptr type in most of interfaces parameters... :P
#Region Interfaces
Global Const $sTagCLRMetaHost = "GetRuntime hresult(wstr;struct*;ptr);" & _
        "GetVersionFromFile hresult(ptr;ptr;ptr);" & _
        "EnumerateInstalledRuntimes hresult(ptr)" & _
        "EnumerateLoadedRuntimes hresult(ptr;ptr)" & _
        "RequestRuntimeLoadedNotification hresult(ptr,ptr,ptr)" & _
        "QueryLegacyV2RuntimeBinding hresult(ptr;ptr)" & _
        "ExitProcess hresult(int)"

Global Const $sTagCLRRuntimeInfo = "GetVersionString hresult(ptr;ptr);" & _
        "GetRuntimeDirectory hresult(ptr;ptr);" & _
        "IsLoaded hresult(ptr;ptr);" & _
        "LoadErrorString hresult(ptr;ptr;ptr;ptr);" & _
        "LoadLibrary hresult(ptr;ptr);" & _
        "GetProcAddress hresult(ptr;ptr);" & _
        "GetInterface hresult(ptr;ptr;ptr);" & _
        "IsLoadable hresult(Bool*);" & _
        "SetDefaultStartupFlags hresult(ptr;ptr);" & _
        "GetDefaultStartupFlags hresult(ptr;ptr;ptr);" & _
        "BindAsLegacyV2Runtime hresult();" & _
        "IsStarted hresult(ptr;ptr);"

Global Const $sTagRuntimeHost = "Start hresult();Stop hresult();SetHostControl hresult(ptr);GetCLRControl hresult(ptr);" & _
        "UnloadAppDomain hresult(ptr;ptr);ExecuteInAppDomain hresult(ptr;ptr;ptr);GetCurrentAppDomainId hresult(ptr);" & _
        "ExecuteApplication hresult(ptr;ptr;ptr;ptr;ptr;ptr);" & _
        "ExecuteInDefaultAppDomain hresult(wstr;wstr;wstr;wstr;ptr*);"
#EndRegion Interfaces


#Region CLSID & IID
Global Const $sCLSID_CLRMetaHost = "{9280188d-0e8e-4867-b30c-7fa83884e8de}"
Global Const $sIID_ICLRMetaHost = "{d332db9e-b9b3-4125-8207-a14884f53216}"
Global Const $sIID_ICLRRuntimeInfo = "{BD39D1D2-BA2F-486a-89B0-B4B0CB466891}"
Global Const $sCLSID_CLRRuntimeHost = "{90F1A06E-7712-4762-86B5-7A5EBA6BDB02}"
Global Const $sIID_ICLRRuntimeHost = "{90F1A06C-7712-4762-86B5-7A5EBA6BDB02}"

Global $tCLSID_CLRMetaHost = _WinAPI_CLSIDFromString($sCLSID_CLRMetaHost)
Global $tIID_ICLRMetaHost = _WinAPI_CLSIDFromString($sIID_ICLRMetaHost)
Global $tIID_ICLRRuntimeInfo = _WinAPI_CLSIDFromString($sIID_ICLRRuntimeInfo)
Global $tCLSID_CLRRuntimeHost = _WinAPI_CLSIDFromString($sCLSID_CLRRuntimeHost)
Global $tIID_ICLRRuntimeHost = _WinAPI_CLSIDFromString($sIID_ICLRRuntimeHost)
#EndRegion CLSID & IID

Local $hMSCorEE = DllOpen("MSCorEE.DLL")

;get ClrHost
Local $aRet = DllCall($hMSCorEE, "long", "CLRCreateInstance", "struct*", $tCLSID_CLRMetaHost, _
        "struct*", $tIID_ICLRMetaHost, "ptr*", 0)



If $aRet[0] = $S_OK Then
    Local $pClrHost = $aRet[3]
    Local $oClrHost = ObjCreateInterface($pClrHost, $sIID_ICLRMetaHost, $sTagCLRMetaHost)
    ConsoleWrite(">oClrHost: " & IsObj($oClrHost) & @CRLF)

    Local $sNETFrameworkVersion = "v4.0.30319"
    Local $tRunInfo = DllStructCreate("ptr")
    $oClrHost.GetRuntime($sNETFrameworkVersion, $tIID_ICLRRuntimeInfo, DllStructGetPtr($tRunInfo))
    Local $pRunInfo = DllStructGetData($tRunInfo, 1)
    ConsoleWrite(">pRunInfo: " & $pRunInfo & @CRLF)

    Local $oRunInfo = ObjCreateInterface($pRunInfo, $sIID_ICLRRuntimeInfo, $sTagCLRRuntimeInfo)
    ConsoleWrite(">oRunInfo: " & IsObj($oRunInfo) & @CRLF)
    Local $isIsLoadable = 0
    $oRunInfo.IsLoadable($isIsLoadable)
    ConsoleWrite(">IsLoadable: " & $isIsLoadable & @CRLF)


#Region Get GetVersionString
    Local $tSize = DllStructCreate("dword Data")
    $tSize.Data = 0
    $oRunInfo.GetVersionString(Null, DllStructGetPtr($tSize, 1)) ;get requiered Size
    ConsoleWrite(">Required Size: " & $tSize.Data & @CRLF)
    Local $tString = DllStructCreate("wchar Data[" & $tSize.Data & "]")
    $oRunInfo.GetVersionString(DllStructGetPtr($tString, 1), DllStructGetPtr($tSize, 1)) ;get Version String
    ConsoleWrite(">Version String: " & $tString.Data & @CRLF)
#EndRegion  Get GetVersionString


;~ #Region C# Library call
;~  If $isIsLoadable Then
;~      Local $tRuntimeHost = DllStructCreate("ptr")
;~      $oRunInfo.GetInterface(DllStructGetPtr($tCLSID_CLRRuntimeHost), DllStructGetPtr($tIID_ICLRRuntimeHost), DllStructGetPtr($tRuntimeHost))
;~      Local $pRuntimeHost = DllStructGetData($tRuntimeHost, 1)
;~      ConsoleWrite(">pRuntimeHost: " & $pRuntimeHost & @CRLF)
;~      Local $oRuntimeHost = ObjCreateInterface($pRuntimeHost, $sIID_ICLRRuntimeHost, $sTagRuntimeHost)
;~      ConsoleWrite(">oRuntimeHost" & IsObj($oRuntimeHost) & @CRLF)
;~      Local $iRet = 0
;~      $oRuntimeHost.Start()
;~      $oRuntimeHost.ExecuteInDefaultAppDomain(@ScriptDir & "\C#Library.dll", "ClassLibraryDemo.ClassDemo", "NetMsgBox", "AutoIt Rocks!!! " & @CRLF & "Danyfirex does too lol!!!", $iRet)
;~      ConsoleWrite(">Ret: " & $iRet & @CRLF)
;~  EndIf
;~ #EndRegion


EndIf

;~ DllClose($hMSCorEE) ;for some reason (Maybe I'll check later) it crashs if I close the libary when I dont use Region C# Library call... lol


Func _WinAPI_CLSIDFromString($sGUID)
    $tGUID = DllStructCreate('ulong Data1;ushort Data2;ushort Data3;byte Data4[8]')
    $iRet = DllCall('ole32.dll', 'uint', 'CLSIDFromString', 'wstr', $sGUID, 'ptr', DllStructGetPtr($tGUID))
    If (@error) Or ($iRet[0]) Then
        Return SetError(@error, @extended, 0)
    EndIf
    Return $tGUID
EndFunc   ;==>_WinAPI_CLSIDFromString

Saludos

Link to comment
Share on other sites

Just another code to get the list of runtime versions.

 

;~ #AutoIt3Wrapper_UseX64=y

Global Const $S_OK = 0

;I'm lazy for that you'll see ptr type in most of interfaces parameters... :P
#Region Interfaces
Global Const $sTagCLRMetaHost = "GetRuntime hresult(wstr;struct*;ptr);" & _
        "GetVersionFromFile hresult(ptr;ptr;ptr);" & _
        "EnumerateInstalledRuntimes hresult(ptr)" & _
        "EnumerateLoadedRuntimes hresult(ptr;ptr)" & _
        "RequestRuntimeLoadedNotification hresult(ptr,ptr,ptr)" & _
        "QueryLegacyV2RuntimeBinding hresult(ptr;ptr)" & _
        "ExitProcess hresult(int)"

Global Const $sTagCLRRuntimeInfo = "GetVersionString hresult(ptr;ptr);" & _
        "GetRuntimeDirectory hresult(ptr;ptr);" & _
        "IsLoaded hresult(ptr;ptr);" & _
        "LoadErrorString hresult(ptr;ptr;ptr;ptr);" & _
        "LoadLibrary hresult(ptr;ptr);" & _
        "GetProcAddress hresult(ptr;ptr);" & _
        "GetInterface hresult(ptr;ptr;ptr);" & _
        "IsLoadable hresult(Bool*);" & _
        "SetDefaultStartupFlags hresult(ptr;ptr);" & _
        "GetDefaultStartupFlags hresult(ptr;ptr;ptr);" & _
        "BindAsLegacyV2Runtime hresult();" & _
        "IsStarted hresult(ptr;ptr);"

Global Const $sTagRuntimeHost = "Start hresult();Stop hresult();SetHostControl hresult(ptr);GetCLRControl hresult(ptr);" & _
        "UnloadAppDomain hresult(ptr;ptr);ExecuteInAppDomain hresult(ptr;ptr;ptr);GetCurrentAppDomainId hresult(ptr);" & _
        "ExecuteApplication hresult(ptr;ptr;ptr;ptr;ptr;ptr);" & _
        "ExecuteInDefaultAppDomain hresult(wstr;wstr;wstr;wstr;ptr*);"

Global Const $sTagEnumUnknown = "Next hresult(ulong;ptr*;ulong); Skip hresult(ptr); Reset hresult(); Clone hresult(ptr);"
#EndRegion Interfaces



#Region CLSID & IID
Global Const $sCLSID_CLRMetaHost = "{9280188d-0e8e-4867-b30c-7fa83884e8de}"
Global Const $sIID_ICLRMetaHost = "{d332db9e-b9b3-4125-8207-a14884f53216}"
Global Const $sIID_ICLRRuntimeInfo = "{BD39D1D2-BA2F-486a-89B0-B4B0CB466891}"
Global Const $sCLSID_CLRRuntimeHost = "{90F1A06E-7712-4762-86B5-7A5EBA6BDB02}"
Global Const $sIID_ICLRRuntimeHost = "{90F1A06C-7712-4762-86B5-7A5EBA6BDB02}"
Global Const $sIID_IEnumUnknown = "{00000100-0000-0000-C000-000000000046}"

Global $tCLSID_CLRMetaHost = _WinAPI_CLSIDFromString($sCLSID_CLRMetaHost)
Global $tIID_ICLRMetaHost = _WinAPI_CLSIDFromString($sIID_ICLRMetaHost)
Global $tIID_ICLRRuntimeInfo = _WinAPI_CLSIDFromString($sIID_ICLRRuntimeInfo)
Global $tCLSID_CLRRuntimeHost = _WinAPI_CLSIDFromString($sCLSID_CLRRuntimeHost)
Global $tIID_ICLRRuntimeHost = _WinAPI_CLSIDFromString($sIID_ICLRRuntimeHost)
Global $tIID_IEnumUnknown = _WinAPI_CLSIDFromString($sIID_IEnumUnknown)
#EndRegion CLSID & IID

Local $hMSCorEE = DllOpen("MSCorEE.DLL")

;get ClrHost
Local $aRet = DllCall($hMSCorEE, "long", "CLRCreateInstance", "struct*", $tCLSID_CLRMetaHost, _
        "struct*", $tIID_ICLRMetaHost, "ptr*", 0)



If $aRet[0] = $S_OK Then
    Local $pClrHost = $aRet[3]
    Local $oClrHost = ObjCreateInterface($pClrHost, $sIID_ICLRMetaHost, $sTagCLRMetaHost)
    ConsoleWrite(">oClrHost: " & IsObj($oClrHost) & @CRLF)

    Local $tEnumerateRuntimes = DllStructCreate("ptr")
    $oClrHost.EnumerateInstalledRuntimes(DllStructGetPtr($tEnumerateRuntimes))
    Local $pEnumerateRuntimes = DllStructGetData($tEnumerateRuntimes, 1)
    ConsoleWrite(">pEnumerateRuntimes: " & $pEnumerateRuntimes & @CRLF)

    Local $oEnumerateRuntimes = ObjCreateInterface($pEnumerateRuntimes, $sIID_IEnumUnknown, $sTagEnumUnknown)
    ConsoleWrite(">oEnumerateRuntimes: " & IsObj($oEnumerateRuntimes) & @CRLF)
    Local $pRuntime = 0
    Local $oRunInfo = 0
    Local $tSize = 0
    Local $tString = 0
    ;List Runtimes
    While $oEnumerateRuntimes.Next(1, $pRuntime, Null) = $S_OK
        $oRunInfo = ObjCreateInterface($pRuntime, $sIID_ICLRRuntimeInfo, $sTagCLRRuntimeInfo)
;~      ConsoleWrite(">oRunInfo: " & IsObj($oRunInfo) & @CRLF)
        #Region Get GetVersionString
        $tSize = DllStructCreate("dword Data")
        $tSize.Data = 0
        $oRunInfo.GetVersionString(Null, DllStructGetPtr($tSize, 1)) ;get requiered Size
;~      ConsoleWrite(">Required Size: " & $tSize.Data & @CRLF)
        $tString = DllStructCreate("wchar Data[" & $tSize.Data & "]")
        $oRunInfo.GetVersionString(DllStructGetPtr($tString, 1), DllStructGetPtr($tSize, 1)) ;get Version String
        ConsoleWrite("+Version String: " & $tString.Data & @CRLF)
        #EndRegion Get GetVersionString
    WEnd
EndIf

;~ DllClose($hMSCorEE)


Func _WinAPI_CLSIDFromString($sGUID)
    $tGUID = DllStructCreate('ulong Data1;ushort Data2;ushort Data3;byte Data4[8]')
    $iRet = DllCall('ole32.dll', 'uint', 'CLSIDFromString', 'wstr', $sGUID, 'ptr', DllStructGetPtr($tGUID))
    If (@error) Or ($iRet[0]) Then
        Return SetError(@error, @extended, 0)
    EndIf
    Return $tGUID
EndFunc   ;==>_WinAPI_CLSIDFromString

Saludos

 

Edited by Danyfirex
typo
Link to comment
Share on other sites

Hi Danyfirex,

Tested all of this as well and runs like a charm and fast too .... you really rock ! :graduated:

added some cleanup code : (stop and release methods)

Local $iRet = 0
        $oRuntimeHost.Start()
        $oRuntimeHost.ExecuteInDefaultAppDomain(@ScriptDir & "\C#Library.dll", "ClassLibraryDemo.ClassDemo", "NetMsgBox", "AutoIt Rocks!!! " & @CRLF & "Danyfirex does too lol!!!", $iRet)
        ConsoleWrite(">Ret: " & $iRet & @CRLF)

    EndIf
    $oClrHost.Release()
    $oRunInfo.Release()
    $oRuntimeHost.Stop()
    $tRuntimeHost.Release()
EndIf

Since you have got your head wrapped around all of the the .NET interfacing. I was wondering how we could get access to the run the  .NET Class Libraries inline.... without having to compile a C# library and accessing it through CLRHost Interface.

Like this : https://support.smartbear.com/testcomplete/docs/testing-with/advanced/using-external-functions/calling-from-dotnet-assemblies.html

Quote

 Dim str, i

  ' Calling a class instance constructor
  Set str = dotNET.System.String.zctor_8(&H41, 3)
  Log.Message str.OleValue ' Using the OleValue property

  ' Calling a static method
  Set str = dotNET.System.String.Copy("Hello, world!")
  ' Calling a class instance (non-static) method
  i = str.IndexOf("w")
  Log.Message i

Or this way : http://www.learnqtp.com/dotnetfactory-qtp-part1-basics/

Quote

Set objForm = DotNetFactory.CreateInstance("System.Windows.Forms.Form", "System.Windows.Forms")
  Set objStartPos = DotNetFactory.CreateInstance("System.Windows.Forms.FormStartPosition","System.Windows.Forms")

  objForm.Text = sTitle

  Select Case sStartPosition
   Case "CENTERSCREEN"

    objForm.StartPosition = objStartPos.CenterScreen

   Case "MANUAL"

    objForm.StartPosition = objStartPos.Manual

   Case Else

    objForm.StartPosition = objStartPos.WindowsDefaultLocation

  End Select

  objForm.Width = intWidth

  objForm.Height = intHeight

  objForm.Left = intLeft

  objForm.Top = intTop
 

 

Link to comment
Share on other sites

never new I could do a shorthand on structs with the dot syntax but cannot find in help file how this should behave

Example 1 on working/not working

;~ Why does this work
Local $tSize = DllStructCreate("dword data2; dword Data")
    $tSize.Data = 0
;~ Why does this fail: Variable must be of type "Object".
Local $tSize = DllStructCreate("wchar[16] data2; dword Data")
    $tSize.Data = 0

Example 2 why not working if in the structure is a member of wchar before my dword pcchBuffer/length value

;~ does not work
;~ Local $mySTRUCT = DllStructCreate("wchar[16] pwzBuffer;dword pcchBuffer")

;~ does work
Local $mySTRUCT = DllStructCreate("dword pwzBuffer;dword pcchBuffer")

;~  $oRunInfo.GetVersionString(null, dllstructgetptr($myStruct,2))
    $oRunInfo.GetVersionString(null, dllstructgetptr($myStruct,"pcchBuffer"))

    ConsoleWrite(">Required Size: " & dllstructgetdata($myStruct,2) & @CRLF)
    ConsoleWrite(">Required Size: " & dllstructgetdata($myStruct,"pcchBuffer") & @CRLF)

I understand @danyfirex code is cleaner. For me its more about learning how to translate this stuff in AutoIt (C/C3/C++ is so much easier) and understanding the details on these definitions in AutoIt

Link to comment
Share on other sites

@ptrex    I really don't understand what you mean :S. (I'll read the page you're talking about as soon I can maybe I'll get your point) or maybe you can get a better C++   example about what you mean.

thanks about cleaning code. I'm no sure if .Release is needed becase I think objCreateInterface do it by itself. I think. ( I'll check this later too) lol

 

@junkew

Example 1 Answer.

First does not works because allocated size should be after dataname

Wrong:

Local $tSize = DllStructCreate("wchar[16] data2; dword Data")

 

Because allocated size should be after dataname like:

Correct:

Local $tSize = DllStructCreate("wchar data2[16]; dword Data")

Example 2 Answer.

Answered with Example 1. It should be:

Local $mySTRUCT = DllStructCreate("wchar pwzBuffer[16];dword pcchBuffer")

 

Local $mySTRUCT = DllStructCreate("dword pwzBuffer;dword pcchBuffer")

and this work because you declare the structure correctly but when you try to use probably you'll get an app crash because method is expecting a pointer to an allocated string.

 

Saludos

 

Edited by Danyfirex
just edit
Link to comment
Share on other sites

Just use

"GetVersionString hresult(wstr;dword*);"

And then

Local $sVer
$oRunInfo.GetVersionString($sVer, 65536)
ConsoleWrite($sVer & @CRLF)

Also dich the use of structs for guids when there you have "clsid" type available

"GetInterface hresult(clsid;clsid;ptr*);"
Local $pRuntimeHost
$oRunInfo.GetInterface($sCLSID_CLRRuntimeHost, $sIID_ICLRRuntimeHost, $pRuntimeHost)

 

Btw, it would be better to enumerate available runtimes and choose from there.

Good job Danyfirex. :kiss:

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

@trancexx thank you lady. You're right. I really know all those types of ObjetCreateItnerface But I'm too lazy to set all correct ones (it does not mean that ptr was wrong) but I dont want to go so deep into  interfaces documentations.  For that I use most of the times ptr type (Also I love working with ptrs and structs...)  ^_^

 

Kisses for you too (here where our romance starts...)  :>

 

Saludos

Edited by Danyfirex
better sence to my answer
Link to comment
Share on other sites

Danyfirex 

According to the description :

https://msdn.microsoft.com/en-us/library/dd233125(v=vs.110).aspx

ICLRRuntimeInfo::LoadLibrary Method
Loads a .NET Framework library from the common language runtime (CLR) represented by an ICLRRuntimeInfo interface.

It's should be possible to  .NET Framework library (not a custom build library) 

like for example :  System.Windows.Forms or System.String or any other native .net class libraries ?

I have searched the net but did not find any examples though...

 

Link to comment
Share on other sites

my logic would be (implicitly assemblies will be loaded with the load function)

CurrentDomain.CreateInstanceFrom(“mscorlib.dll, “system.string")

or with 

gettype("system.string")

found by reading around on ironpython and dynamic language runtime (on top of clr)

 

edit: some other references to go thru

  • Type.GetType(“System.Int32”) can return type System.Int32 without mentioning mscorlib.dll.
  • CreateInstanceAndUnwrap method
    https://msdn.microsoft.com/en-us/library/3c4f1xde(v=vs.113).aspx
  • Current domain (deprecated in version 4??)
    https://msdn.microsoft.com/en-us/library/ms164326(v=vs.110).aspx
  • AppDomains
    When the CLR COM server initializes, it creates an AppDomain. An AppDomain is a logical container for a set of assemblies. The first AppDomain created when the CLR is initialized is called the default AppDomain; this AppDomain is destroyed only when the Windows process terminates.
    In addition to the default AppDomain, a host using either unmanaged COM interface methods or managed type methods can instruct the CLR to create additional AppDomains. The whole purpose of an AppDomain is to provide isolation. Here are the specific features offered by an AppDomain:
ICorRuntimeHost::GetDefaultDomain
HRESULT GetDefaultDomain (  
    [out] IUnknown** pAppDomain  
);
Edited by junkew
extended with some additional reading
Link to comment
Share on other sites

Hi All,

To make this solution more attractive / interesting there are 2 steps to investigate how to :

1. Access to the native .Net Class libraries (if possible not to have the DLL to loads first)

2. Run C# code inline .... using the inline compilation of the IL code.

    Then there is no need to do pre-compilation to .Net DLL.

3. Optionally is to be able to compile the inline C# code to a DLL / EXE.

 

I will try to find out some articles where this is explained... next is that we need some to translate this to au3 code.

ptrex

Link to comment
Share on other sites

@junkew 

The "CreateInstanceAndUnwrap Method" is a beta release an can be subject to changes as is mentioned in the article.

The approach I found to be used would be :

Retrieve default domain by ICorRuntimeHost::CreateDomain/GetDefaultDomain, and after use it to instantiate class instance - e.g. AppDomain.CreateInstanceFrom.

1. ICorRuntimeHost::CreateDomain Method

2. ICorRuntimeHost::GetDefaultDomain Method

3. AppDomain.CreateInstanceFrom Method

Hopefully DanyFirex can give us a hand to convert this in au3 code ?

 

Link to comment
Share on other sites

Although its C++ it shows you can directly instantiate a system.int32 from unmanaged code

maybe in 2 steps this has to be transformed to createinstance followed by an unwrap

#using <mscorlib.dll>
#include "stdafx.h"
using namespace System;
using namespace System::Reflection;

static void InstantiateINT32(bool ignoreCase) {
	try {
		AppDomain^  currentDomain = AppDomain::CurrentDomain;
		Object^ instance = currentDomain->CreateInstanceAndUnwrap("mscorlib",
			"SYSTEM.INT32",	
			ignoreCase,	
			BindingFlags::Default,
			nullptr,
			nullptr,
			nullptr,
			nullptr,
			nullptr);
		Console::WriteLine(instance->GetType());
	}
	catch (TypeLoadException^ e) {
		Console::WriteLine(e->Message);
	}
}

int main() {
	InstantiateINT32(false);     // Failed!
	InstantiateINT32(true);      // OK!
}

and this works nicely in VBA excel (early binding, no late binding) and helps in understanding the cor runtime as its easier walking thru in debugmode of VBA ide

just set the reference to mscoree.tlb and mscorlib.tlb (classes are case sensitive)

Sub test()
    Dim rt As mscoree.CorRuntimeHost
    Dim unk As stdole.IUnknown
    Dim ad As mscorlib.AppDomain
    Dim s As mscorlib.Stack
    
    Set rt = New mscoree.CorRuntimeHost
    rt.Start
    rt.GetDefaultDomain unk
    Set ad = unk
    Set s = ad.CreateInstance("mscorlib", "System.Collections.Stack").Unwrap
    s.Push "hello"
    s.Push "goodbye"
    s.Push 42
    
    MsgBox s.Pop
    MsgBox s.Pop
    MsgBox s.Pop
End Sub

this works not

Sub test2()
    Dim rt As mscoree.CorRuntimeHost
    Dim unk As stdole.IUnknown
    Dim ad As mscorlib.AppDomain
    Dim s As mscorlib.ObjectHandle
    
    
    Set rt = New mscoree.CorRuntimeHost
    rt.Start
    rt.GetDefaultDomain unk
    Set ad = unk
    'System.Runtime.Remoting.ObjectHandle
    Set s = ad.CreateInstance("mscorlib", "System.Int32") '.Unwrap
   ' .Unwrap
        
      
Debug.Print s

End Sub

First get it running in VBA and when found out how to do late binding with createinstance it should not be hard

Edited by junkew
fixed c++ code based on VS2015 CE
Link to comment
Share on other sites

This is exactly the same for when investigating COM objects :) 

Using the VBA Object browser gives you all the details you need about the methods / properties / events etc.

It's good workbench for testing indeed...

I will also do some more reading on this, but a bit short of time these days, so hold on for a while ...

Thanks for keeping this alive !

Link to comment
Share on other sites

  • Melba23 pinned and unpinned this topic

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...