Jump to content

Using .NET libary with AutoIt, possible?


Recommended Posts

The only one I got running is this one : System.Runtime.Hosting.ApplicationActivator

All the rest of the CLSID relating to the activator did not return any results ...

#AutoIt3Wrapper_Version=beta
#AutoIt3Wrapper_UseX64=Y

Global $hActiveX

; Load the System modules
If @AutoItX64 Then
    $hActiveX  = DllOpen("C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorlib.tlb")
Else
    $hActiveX  = DllOpen("C:\Windows\Microsoft.NET\Framework64\v2.0.50727\mscorlib.tlb")
EndIf
;MsgBox(0,"x64",@AutoItX64)

; Object identifiers
Global Const $sCLSID = "{1D09B407-A97F-378A-ACCB-82CA0082F9F3}"
;Global Const $sIID = "{03973551-57A1-3900-A2B5-9083E3FF2943}"
Global Const $sIID = Default ; Or use keyword Default if you want to use the Default interface ID

; COM Error monitoring
Global $oError = ObjEvent("AutoIt.Error", "_ErrFunc")

Func _ErrFunc()
    ConsoleWrite("! COM Error ! Number: 0x" & Hex($oError.number, 8) & " ScriptLine: " & $oError.scriptline & " - " & $oError.windescription & @CRLF)
    Return
EndFunc    ;==>_ErrFunc

; Create  COM Object
Local $oDotNET = ObjCreate($sCLSID, $sIID, $hActiveX)

If $oDotNET = 0 Then MsgBox(16,"Error", "Could not create the object, Common problem ActiveX not registered.")

; This will create a System.Random Number
ConsoleWrite("System.Activator # : " & isobj($oDotNET) & @CRLF)
ConsoleWrite($oDotNET.ToString() & @CRLF & @CRLF)

$oDotNET = ""
DllClose($hActiveX)

 

Link to comment
Share on other sites

ApplicationActivator is a different purpose then system.activator.

namespace System.Runtime.InteropServices
{
    /// <summary>Exposes the <see cref="T:System.Activator" /> class to unmanaged code.</summary>
    [CLSCompliant(false), ComVisible(true), Guid("03973551-57A1-3900-A2B5-9083E3FF2943"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), TypeLibImportClass(typeof(Activator))]
    public interface _Activator
  • and otherwise a C# piece of code as a helper doing just this
return _activator;

 

  • I do not have a clue how to do it from unmanaged code at all.
    Will try a little further with system.runtime.interopservices assembly but am close to give up to do this within AutoIt natively.

 

 

 

Link to comment
Share on other sites

Indeed the class is Com Visible if I look in ILSpy ...

Quote

    [__DynamicallyInvokable, ClassInterface(ClassInterfaceType.None), ComDefaultInterface(typeof(_Activator)), ComVisible(true)]

But looking at this info here it should be possible

http://stackoverflow.com/questions/465488/can-i-load-a-net-assembly-at-runtime-and-instantiate-a-type-knowing-only-the-na

But I also can't seem to get it to run ...

Link to comment
Share on other sites

Summarized regarding activator

[
      uuid(9BA4FD4E-2BC2-31A0-B721-D17ABA5B12C3),
      version(1.0),
      noncreatable,
      custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "System.Activator")
    ]
    coclass Activator {
        interface _Object;
        [default] interface _Activator;
    };
  • system.runtime.interopservices seems to give all possibilities on marshalling structs to ptr and vice versa if you want to integrate more AutoIt and .NET language there are possibilities
  • .NET CLR Activator - GetType.au3  is incorrect as its given a complete incorrect interface definition
    However as it gives back a ptr and it creates an object maybe just add the 4 activator methods (equal to IDispatch)
    interface _Activator : IUnknown {
            HRESULT _stdcall GetTypeInfoCount([out] unsigned long* pcTInfo);
            HRESULT _stdcall GetTypeInfo([in] unsigned long iTInfo, [in] unsigned long lcid, [in] long ppTInfo);
            HRESULT _stdcall GetIDsOfNames([in] GUID* riid, [in] long rgszNames,[in] unsigned long cNames,[in] unsigned long lcid,[in] long rgDispId);
            HRESULT _stdcall Invoke([in] unsigned long dispIdMember,[in] GUID* riid,[in] unsigned long lcid, 
                            [in] short wFlags, [in] long pDispParams,[in] long pVarResult,[in] long pExcepInfo,[in] long puArgErr);
        };
    Even if that works we should get to the other interfaces like _object
    or
    then we get invoke("createinstance",....) syntax
  • mscorlib_TLB.pas (Google for it)  seems to give partial the answer
    https://sourceforge.net/p/whitestaruml/code-0/270/tree/trunk/Imports/mscorlib_TLB.pas
  •  

 

 

 

 

Link to comment
Share on other sites

Understanding : clsid 0F21F359-AB84-41E8-9A78-36D110E6D2F9  

See page 562 

http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.465.6546&rep=rep1&type=pdf

Quote

Understand that this custom attribute is completely ignored by COM clients, unless you explicitly build a COM solution that is on the lookout for this name/value pair

The more you read about it the more complex it get's ... This 700 pages guide is something to read whenever you really get bored ...

Link to comment
Share on other sites

Over the years it gets easier. I learned long ago assembler so when I see in .NET we invented Intermediate Language assembly and now we have invented webassembly it al goes down to the same patterns of abstraction layers. Study Arduino and you learn its all about electricity flowing around :)

Will put the book you shared to post 4 as it gives proper insight on how to deal with structures like point, size of the win32 API or for the WPF Forms.

reading this book http://www.apress.com/us/book/9781484213339 from same author as reference you shared

and I am sure that this guy can tell easily what we have not yet found out in this thread how to do it in AutoIt

Link to comment
Share on other sites

Link to comment
Share on other sites

Standard gives some indication on how to handle value types and struct and how to deal with unmanaged to managed. Basically all is a ptr. Passing point and size should most likely be a ptr. Not enough time to try but some paragraphs in this standard doc gives a good guidance.

http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-335.pdf

And if bored memorize all opcodes in the document:)

Link to comment
Share on other sites

Nice documentation again... 

We have now gather more documentation than we we can every read, let it be understand ?

Maybe it's time to summarize and chop the elephant in pieces.

By listing out the individual topics that are not working, like :

- CLR.au3 still incomplete ( and maybe one of the root causes things are not working)

- Retrieving static constants, not working (cfr.  "System.Math.PI")

- Retrieving enums not working

- GetTypes : Safe Array Elements are not returning

- GUI Objects, not working fully (linked to the above missing topics)

- ....

So maybe we need to take again a step back and look at the CLR.au3, to see what is missing there already to start with.

For example to get a simple example working like : System.Math.PI

This might give more insight and get the ball rolling for other Types... just to get started somewhere ... ?

 

 

 

 

Link to comment
Share on other sites

Most of those documents I have been reading first before posting :) to understand it better and have examples nicely working compiled in visual studio with C++ or C#.

Its just a small missing piece on how to transform to AutoIt

Conclusion:

  • Current CLR.AU3 offers already more then OP asked in first post:D
  • yes, it all can be done but there have not been many people on this path to do it from unmanaged code.
    Plenty of examples for managed code
  • Missing some insight / documentation on ObjCreate/ObjCreateinterface (maybe contact the developers for the C++ coding source of these functions)
  • System.Activator I think I get that one to work coming 2 weeks and maybe easy by just adding iDispatch interface to clr.au3 for ITypeActivator
  • Wanted to make an example with CLR 4.0 for system.numerics.biginteger
  • And in the documents / references its clearly stated that not all win32 api structs/enums etc are in .NET by default and solutions are
    • pass pointer to .NET
    • make wrapper class in .NET with reflection and/or with clr v4 use dynamic keyword
    • As I work frequently with HP UFT and dotnetfactory looking in the assembly shows that there is just some overloading on createinstance but no real magic
  • I learned a lot but just not enough yet to understand passing POINT/SIZE structures and not enough time to experiment in AutoIt

 

 

 

Link to comment
Share on other sites

"its just a small missing piece on how to transform to AutoIt"  

Not sure at this moment who is still in the developer team ? 

For the  ObjCreateinterface you can try to PM trancexx.

Anyone who can help to clarify this is welcome ... 

In the meantime I will try to test some more examples to see what I can get working or not working ... 

Link to comment
Share on other sites

@trancexx Can you say something on below code and maybe elaborate a bit on the concepts where I am doing it wrong

According to mscorlib.idl the system.activator is based on IUnknown.

Within the example I do get a pointer but unable to instantiate when giving the tagDefinition or even when giving Default as a parameter it goes wrong.

To my surprise I do get an object when i give a WRONG definition of IType with it.

#AutoIt3Wrapper_UseX64=n

#include "CLR.Au3"
#include <WinAPI.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <StructureConstants.au3>
example()
Func Example()
    $sIID_IUnknown = "{00000000-0000-0000-C000-000000000046}"
    ; Definition
    $stagIUnknown = "QueryInterface hresult(ptr;ptr*);" & _
        "AddRef dword();" & _
        "Release dword();"

    $sIID__Activator = "{03973551-57A1-3900-A2B5-9083E3FF2943}"
    $tCLSID__Activator = _WinAPI_CLSIDFromString($sCLSID_CLRRuntimeHost)

;~ This IDispatch is in CLR.AU3 defined
;~ Global Const $sIID_IDispatch = "{00020400-0000-0000-C000-000000000046}"
;~ Global Const $sTag_IDispatch = _
;~      "GetTypeInfoCount hresult(dword*);" & _ ; Retrieves the number of type information interfaces that an object provides (either 0 or 1).
;~      "GetTypeInfo hresult(dword;dword;ptr*);" & _ ; Gets the type information for an object.
;~      "GetIDsOfNames hresult(ptr;ptr;dword;dword;ptr);" & _ ; Maps a single member and an optional set of argument names to a corresponding set of integer DISPIDs, which can be used on subsequent calls to Invoke.
;~      "Invoke hresult(dword;ptr;dword;word;ptr;ptr;ptr;ptr);" ; Provides access to properties and methods exposed by an object.

    $sTag_Activator =  $stagIUnknown & $sTag_IDispatch
    consolewrite( $sTag_Activator  & @CRLF)

    Local $oAssembly = _CLR_LoadLibrary("mscorlib")
    ConsoleWrite("!$oAssembly: " & IsObj($oAssembly) & @CRLF)

    Local $pType
    $oAssembly.GetType_2("System.Activator",$pType)
    ConsoleWrite("!$pType: " & ptr($pType) & @CRLF)

    Local $oType = ObjCreateInterface($pType, $sIID__Activator, $sTag_Activator )
    ConsoleWrite("System.Activator IsObj( $oType ) = " & IsObj($oType) & @CRLF)

    Local $oType = ObjCreateInterface($pType, $sIID__Activator, "default", True )
    ConsoleWrite("System.Activator IsObj( $oType ) = " & IsObj($oType) & @CRLF)
    
    Local $oType = ObjCreateInterface($pType, $sIID_IType, $sTag_Itype, True )
    ConsoleWrite("System.Activator IsObj( $oType ) = " & IsObj($oType) & @CRLF)

EndFunc   ;==>Example

for reference the mdl

[
      odl,
      uuid(03973551-57A1-3900-A2B5-9083E3FF2943),
      version(1.0),
      oleautomation,
      custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "System.Activator")    

    ]
    interface _Activator : IUnknown {
        HRESULT _stdcall GetTypeInfoCount([out] unsigned long* pcTInfo);
        HRESULT _stdcall GetTypeInfo(
                        [in] unsigned long iTInfo, 
                        [in] unsigned long lcid, 
                        [in] long ppTInfo);
        HRESULT _stdcall GetIDsOfNames(
                        [in] GUID* riid, 
                        [in] long rgszNames, 
                        [in] unsigned long cNames, 
                        [in] unsigned long lcid, 
                        [in] long rgDispId);
        HRESULT _stdcall Invoke(
                        [in] unsigned long dispIdMember, 
                        [in] GUID* riid, 
                        [in] unsigned long lcid, 
                        [in] short wFlags, 
                        [in] long pDispParams, 
                        [in] long pVarResult, 
                        [in] long pExcepInfo, 
                        [in] long puArgErr);
    };

    [
      uuid(9BA4FD4E-2BC2-31A0-B721-D17ABA5B12C3),
      version(1.0),
      noncreatable,
      custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "System.Activator")
    ]
    coclass Activator {
        interface _Object;
        [default] interface _Activator;
    };

 

Link to comment
Share on other sites

^^ Object description (tag) is irrelevant. It can be anything as long as it's syntactically correct.
For example the help file example could've been written like this:

#include <MsgBoxConstants.au3>

Example()

Func Example()
    ; Declare the CLSID, IID and interface description for ITaskbarList.
    ; It is not necessary to describe the members of IUnknown.
    Local Const $sCLSID_TaskbarList = "{56FDF344-FD6D-11D0-958A-006097C9A090}"
    Local Const $sIID_ITaskbarList = "{56FDF342-FD6D-11D0-958A-006097C9A090}"
    Local Const $sTagITaskbarList = "DoThatFirstThing hresult(); AddTab hresult(hwnd); GetTheFuckAway hresult(hwnd); ActivateTab hresult(hwnd); SetActiveAlt hresult(hwnd);"

    ; Create the object.
    Local $oTaskbarList = ObjCreateInterface($sCLSID_TaskbarList, $sIID_ITaskbarList, $sTagITaskbarList)

    ; Initialize the iTaskbarList object.
    $oTaskbarList.DoThatFirstThing()

    ; Run Notepad.
    Run("notepad.exe")

    ; Wait for the Notepad window to appear and get a handle to it.
    Local $hNotepad = WinWait("[CLASS:Notepad]")

    ; Tell the user what to look for.
    MsgBox($MB_SYSTEMMODAL, "", "Look in the Taskbar and you should see an entry for Notepad." & @CRLF & @CRLF & "Press OK to continue.")

    ; Delete the Notepad entry from the Taskbar.
    $oTaskbarList.GetTheFuckAway($hNotepad)

    ; Tell the user to look again.
    MsgBox($MB_SYSTEMMODAL, "", "Look in the Taskbar.  There should no longer be a Notepad entry but Notepad is still running." & @CRLF & @CRLF & "Press OK to continue.")

    ; Close Notepad.
    WinClose($hNotepad)
EndFunc

 

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

Hello guys-girls. 

@junkew I'm no sure about what you're trying to do but try something like this:

 

#AutoIt3Wrapper_UseX64=n

#include ".\Includes\CLR.au3"
#include <WinAPI.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <StructureConstants.au3>
Example()
Func Example()
    $sIID_IUnknown = "{00000000-0000-0000-C000-000000000046}"
    ; Definition
    $stagIUnknown = "QueryInterface hresult(ptr;ptr*);" & _
            "AddRef dword();" & _
            "Release dword();"

    $sIID__Activator = "{03973551-57A1-3900-A2B5-9083E3FF2943}"
    $tCLSID__Activator = _WinAPI_CLSIDFromString($sCLSID_CLRRuntimeHost)

;~ This IDispatch is in CLR.AU3 defined
;~ Global Const $sIID_IDispatch = "{00020400-0000-0000-C000-000000000046}"
;~ Global Const $sTag_IDispatch = _
;~      "GetTypeInfoCount hresult(dword*);" & _ ; Retrieves the number of type information interfaces that an object provides (either 0 or 1).
;~      "GetTypeInfo hresult(dword;dword;ptr*);" & _ ; Gets the type information for an object.
;~      "GetIDsOfNames hresult(ptr;ptr;dword;dword;ptr);" & _ ; Maps a single member and an optional set of argument names to a corresponding set of integer DISPIDs, which can be used on subsequent calls to Invoke.
;~      "Invoke hresult(dword;ptr;dword;word;ptr;ptr;ptr;ptr);" ; Provides access to properties and methods exposed by an object.

    $sTag_Activator = $stagIUnknown & $sTag_IDispatch
    ConsoleWrite($sTag_Activator & @CRLF)


    Local $oAssembly = _CLR_LoadLibrary("mscorlib")
    ConsoleWrite("$oAssembly: " & IsObj($oAssembly) & @CRLF)

    Local $pAssemblyType = 0
    $oAssembly.GetType_2("System.Activator", $pAssemblyType)
    ConsoleWrite("$pAssemblyType = " & Ptr($pAssemblyType) & @CRLF)

    Local $oAssemblyType = ObjCreateInterface($pAssemblyType, $sIID_IType, $sTag_IType)
    ConsoleWrite("IsObj( $oAssemblyType ) = " & IsObj($oAssemblyType) & @TAB & @CRLF)

    Local $aText[] = ["mscorlib", "System.Collections.Stack"]
    Local $pObject = 0
    $oAssemblyType.InvokeMember_3("CreateInstance", 0x158, 0, 0, CreateSafeArray($aText), $pObject)
    ConsoleWrite("IsObject: " & IsObj($pObject) & @TAB & "$pObject: " & $pObject & @CRLF)

    Local $oStack = $pObject.Unwrap()
    ConsoleWrite("!$oStack: " & IsObj($oStack) & @CRLF)
    $oStack.Push("Bye Bye...")
    $oStack.Push("I Love AutoIt...")
    $oStack.Push("AutoIt Rocks...")

    For $i = 0 To $oStack.Count() - 1
        MsgBox(0, "Stack Example", $oStack.Pop())
    Next


EndFunc   ;==>Example

 

Saludos

 

 

Link to comment
Share on other sites

Nice.

With system.activator you should be able to create system.int32 and some other typevalues. Also structs for point and size should be possible according to msdn documentation.

So there are subtle differences in the createinstance overloads of .net

 

Link to comment
Share on other sites

The only part I do not understand why to use 

$sIID_IType

instead of 

$sIID_IActivator

@ptrex Apparently it turns out my post 91 was already correct to get system.activator but about 110 post(s) later we have now an example that uses it and only leaves me with an understanding question which is less relevant for the moment

  • So leaves mainly to find out how to deal with Structures and Enums to pass point/size to methods for drawing and form classes
Link to comment
Share on other sites

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...