Jump to content

Using .NET libary with AutoIt, possible?


Recommended Posts

  • updated post 4 & 6 with some documentation/cleanup
     
  • A better interface definition for IAppdomainbased on some AIO Wrapper Generator stuff and manual changes. 
    Unsure how to validate (high level compared with MIDL) uncertain on types like variant
    should this get_ be removed? get_ToString --> ToString?
    when to use ptr* or object*?
Global Const $sIID_IAppDomain ="{05F696DC-2B29-3663-AD8B-C4389CF2A713}"
Global Const $sTag_IAppDomain = _
    $sTag_IDispatch & _
    "get_ToString hresult(bstr*);" & _
    "Equals hresult(variant;short*);" & _
    "GetHashCode hresult(int*);" & _
    "GetType hresult(ptr*);" & _
    "InitializeLifetimeService hresult(variant*);" & _
    "GetLifetimeService hresult(variant*);" & _
    "get_Evidence hresult(ptr*);" & _
    "add_DomainUnload hresult(ptr);" & _
    "remove_DomainUnload hresult(ptr);" & _
    "add_AssemblyLoad hresult(ptr);" & _
    "remove_AssemblyLoad hresult(ptr);" & _
    "add_ProcessExit hresult(ptr);" & _
    "remove_ProcessExit hresult(ptr);" & _
    "add_TypeResolve hresult(ptr);" & _
    "remove_TypeResolve hresult(ptr);" & _
    "add_ResourceResolve hresult(ptr);" & _
    "remove_ResourceResolve hresult(ptr);" & _
    "add_AssemblyResolve hresult(ptr);" & _
    "remove_AssemblyResolve hresult(ptr);" & _
    "add_UnhandledException hresult(ptr);" & _
    "remove_UnhandledException hresult(ptr);" & _
    "DefineDynamicAssembly hresult(ptr;int;ptr*);" & _
    "DefineDynamicAssembly_2 hresult(ptr;ptr;bstr;ptr*);" & _
    "DefineDynamicAssembly_3 hresult(ptr;ptr;ptr;ptr*);" & _
    "DefineDynamicAssembly_4 hresult(ptr;ptr;ptr;ptr;ptr;ptr*);" & _
    "DefineDynamicAssembly_5 hresult(ptr;ptr;bstr;ptr;ptr*);" & _
    "DefineDynamicAssembly_6 hresult(ptr;ptr;bstr;ptr;ptr;ptr;ptr*);" & _
    "DefineDynamicAssembly_7 hresult(ptr;ptr;ptr;ptr;ptr;ptr;ptr*);" & _
    "DefineDynamicAssembly_8 hresult(ptr;ptr;bstr;ptr;ptr;ptr;ptr;ptr*);" & _
    "DefineDynamicAssembly_9 hresult(ptr;ptr;bstr;ptr;ptr;ptr;ptr;short;ptr*);" & _
    "CreateInstance hresult(bstr;bstr;ptr*);" & _
    "CreateInstanceFrom hresult(bstr;bstr;ptr*);" & _
    "CreateInstance_2 hresult(bstr;bstr;ptr;ptr*);" & _
    "CreateInstanceFrom_2 hresult(bstr;bstr;ptr;ptr*);" & _
    "CreateInstance_3 hresult(bstr;bstr;short;ptr;ptr;ptr;ptr;ptr;ptr;ptr*);" & _
    "CreateInstanceFrom_3 hresult(bstr;bstr;short;ptr;ptr;ptr;ptr;ptr;ptr;ptr*);" & _
    "Load hresult(ptr;ptr*);" & _
    "Load_2 hresult(bstr;ptr*);" & _
    "Load_3 hresult(ptr;ptr*);" & _
    "Load_4 hresult(ptr;ptr;ptr*);" & _
    "Load_5 hresult(ptr;ptr;ptr;ptr*);" & _
    "Load_6 hresult(ptr;ptr;ptr*);" & _
    "Load_7 hresult(bstr;ptr;ptr*);" & _
    "ExecuteAssembly hresult(bstr;ptr;int*);" & _
    "ExecuteAssembly_2 hresult(bstr;int*);" & _
    "ExecuteAssembly_3 hresult(bstr;ptr;ptr;int*);" & _
    "get_FriendlyName hresult(bstr*);" & _
    "get_BaseDirectory hresult(bstr*);" & _
    "get_RelativeSearchPath hresult(bstr*);" & _
    "get_ShadowCopyFiles hresult(short*);" & _
    "GetAssemblies hresult(ptr);" & _
    "AppendPrivatePath hresult(bstr);" & _
    "ClearPrivatePath hresult();" & _
    "SetShadowCopyPath hresult(bstr);" & _
    "ClearShadowCopyPath hresult();" & _
    "SetCachePath hresult(bstr);" & _
    "SetData hresult(bstr;variant);" & _
    "GetData hresult(bstr;variant*);" & _
    "SetAppDomainPolicy hresult(ptr);" & _
    "SetThreadPrincipal hresult(ptr);" & _
    "SetPrincipalPolicy hresult(ptr);" & _
    "DoCallBack hresult(ptr);" & _
    "get_DynamicDirectory hresult(bstr*);"
  • Why is only from below the first line working?
Local $oAppDomain = ObjCreateInterface($pAppDomain, $sIID_IAppDomain, $sTag_IAppDomain)
;~          Local $oAppDomain = ObjCreateInterface($pAppDomain, $sIID_IAppDomain, Default)
;~          Local $oAppDomain = ObjCreateInterface($pAppDomain, $sIID_IAppDomain)

To me it looks a "normal" iUnknown and iDispatch see below MIDL part

  • [
          odl,
          uuid(05F696DC-2B29-3663-AD8B-C4389CF2A713),
          version(1.0),
          oleautomation,
          custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "System._AppDomain")    
    
        ]
        interface _AppDomain : 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);

     

 

Edited by junkew
Link to comment
Share on other sites

 

improved IType

  • Global Const $sIID_IType = "{BCA8B44D-AAD6-3A86-8AB7-03349F4F2DA2}"
    Global Const $sTag_IType = _
        $sTag_IDispatch & _
        "get_ToString hresult(bstr*);" & _
        "Equals hresult(variant;short*);" & _
        "GetHashCode hresult(int*);" & _
        "GetType hresult(ptr);" & _
        "get_MemberType hresult(ptr);" & _
        "get_name hresult(bstr*);" & _
        "get_DeclaringType hresult(ptr);" & _
        "get_ReflectedType hresult(ptr);" & _
        "GetCustomAttributes hresult(ptr;short;ptr);" & _
        "GetCustomAttributes_2 hresult(short;ptr);" & _
        "IsDefined hresult(ptr;short;short*);" & _
        "get_Guid hresult(ptr);" & _
        "get_Module hresult(ptr);" & _
        "get_Assembly hresult(ptr*);" & _
        "get_TypeHandle hresult(ptr);" & _
        "get_FullName hresult(bstr*);" & _
        "get_Namespace hresult(bstr*);" & _
        "get_AssemblyQualifiedName hresult(bstr*);" & _
        "GetArrayRank hresult(int*);" & _
        "get_BaseType hresult(ptr);" & _
        "GetConstructors hresult(ptr;ptr);" & _
        "GetInterface hresult(bstr;short;ptr);" & _
        "GetInterfaces hresult(ptr);" & _
        "FindInterfaces hresult(ptr;variant;ptr);" & _
        "GetEvent hresult(bstr;ptr;ptr);" & _
        "GetEvents hresult(ptr);" & _
        "GetEvents_2 hresult(int;ptr);" & _
        "GetNestedTypes hresult(int;ptr);" & _
        "GetNestedType hresult(bstr;ptr;ptr);" & _
        "GetMember hresult(bstr;ptr;ptr;ptr);" & _
        "GetDefaultMembers hresult(ptr);" & _
        "FindMembers hresult(ptr;ptr;ptr;variant;ptr);" & _
        "GetElementType hresult(ptr);" & _
        "IsSubclassOf hresult(ptr;short*);" & _
        "IsInstanceOfType hresult(variant;short*);" & _
        "IsAssignableFrom hresult(ptr;short*);" & _
        "GetInterfaceMap hresult(ptr;ptr);" & _
        "GetMethod hresult(bstr;ptr;ptr;ptr;ptr;ptr);" & _
        "GetMethod_2 hresult(bstr;ptr;ptr);" & _
        "GetMethods hresult(int;ptr);" & _
        "GetField hresult(bstr;ptr;ptr);" & _
        "GetFields hresult(int;ptr);" & _
        "GetProperty hresult(bstr;ptr;ptr);" & _
        "GetProperty_2 hresult(bstr;ptr;ptr;ptr;ptr;ptr;ptr);" & _
        "GetProperties hresult(ptr;ptr);" & _
        "GetMember_2 hresult(bstr;ptr;ptr);" & _
        "GetMembers hresult(int;ptr);" & _
        "InvokeMember hresult(bstr;ptr;ptr;variant;ptr;ptr;ptr;ptr;variant*);" & _
        "get_UnderlyingSystemType hresult(ptr);" & _
        "InvokeMember_2 hresult(bstr;int;ptr;variant;ptr;ptr;variant*);" & _
        "InvokeMember_3 hresult(bstr;int;ptr;variant;ptr;variant*);" & _
        "GetConstructor hresult(ptr;ptr;ptr;ptr;ptr;ptr);" & _
        "GetConstructor_2 hresult(ptr;ptr;ptr;ptr;ptr);" & _
        "GetConstructor_3 hresult(ptr;ptr);" & _
        "GetConstructors_2 hresult(ptr);" & _
        "get_TypeInitializer hresult(ptr);" & _
        "GetMethod_3 hresult(bstr;ptr;ptr;ptr;ptr;ptr;ptr);" & _
        "GetMethod_4 hresult(bstr;ptr;ptr;ptr);" & _
        "GetMethod_5 hresult(bstr;ptr;ptr);" & _
        "GetMethod_6 hresult(bstr;ptr);" & _
        "GetMethods_2 hresult(ptr);" & _
        "GetField_2 hresult(bstr;ptr);" & _
        "GetFields_2 hresult(ptr);" & _
        "GetInterface_2 hresult(bstr;ptr);" & _
        "GetEvent_2 hresult(bstr;ptr);" & _
        "GetProperty_3 hresult(bstr;ptr;ptr;ptr;ptr);" & _
        "GetProperty_4 hresult(bstr;ptr;ptr;ptr);" & _
        "GetProperty_5 hresult(bstr;ptr;ptr);" & _
        "GetProperty_6 hresult(bstr;ptr;ptr);" & _
        "GetProperty_7 hresult(bstr;ptr);" & _
        "GetProperties_2 hresult(ptr);" & _
        "GetNestedTypes_2 hresult(ptr);" & _
        "GetNestedType_2 hresult(bstr;ptr);" & _
        "GetMember_3 hresult(bstr;ptr);" & _
        "GetMembers_2 hresult(ptr);" & _
        "get_Attributes hresult(ptr);" & _
        "get_IsNotPublic hresult(short*);" & _
        "get_IsPublic hresult(short*);" & _
        "get_IsNestedPublic hresult(short*);" & _
        "get_IsNestedPrivate hresult(short*);" & _
        "get_IsNestedFamily hresult(short*);" & _
        "get_IsNestedAssembly hresult(short*);" & _
        "get_IsNestedFamANDAssem hresult(short*);" & _
        "get_IsNestedFamORAssem hresult(short*);" & _
        "get_IsAutoLayout hresult(short*);" & _
        "get_IsLayoutSequential hresult(short*);" & _
        "get_IsExplicitLayout hresult(short*);" & _
        "get_IsClass hresult(short*);" & _
        "get_IsInterface hresult(short*);" & _
        "get_IsValueType hresult(short*);" & _
        "get_IsAbstract hresult(short*);" & _
        "get_IsSealed hresult(short*);" & _
        "get_IsEnum hresult(short*);" & _
        "get_IsSpecialName hresult(short*);" & _
        "get_IsImport hresult(short*);" & _
        "get_IsSerializable hresult(short*);" & _
        "get_IsAnsiClass hresult(short*);" & _
        "get_IsUnicodeClass hresult(short*);" & _
        "get_IsAutoClass hresult(short*);" & _
        "get_IsArray hresult(short*);" & _
        "get_IsByRef hresult(short*);" & _
        "get_IsPointer hresult(short*);" & _
        "get_IsPrimitive hresult(short*);" & _
        "get_IsCOMObject hresult(short*);" & _
        "get_HasElementType hresult(short*);" & _
        "get_IsContextful hresult(short*);" & _
        "get_IsMarshalByRef hresult(short*);" & _
        "Equals_2 hresult(ptr;short*);"

 

Link to comment
Share on other sites

Nice documentation cleanup... I will add post 4 & 6 to the other thread So that everyone can easily find it....

Thanks for the improved Interface code... is this already tested and can we update the UDF using this code or just wait for further testing ?

"The proof in the pudding "  As you know AutoIt comes with a .NET Assembly that Jon released a few years ago.

So I thought I would use PowerShell to dive into the Assembly and get any useful information regarding Data Types and more ...

Quote

CLS

$sFile = "C:\Program Files (x86)\AutoIt3\Beta\AutoItX\AutoItX3.Assembly.dll"

$assembly = [Reflection.Assembly]::Loadfile($sFile) 

$assembly.gettype().FullName

#$oAu3 = New-Object AutoIt.AutoItX (New Object does not work because it is not in the GAC)

[AutoIt.AutoItX].GUID

[AutoIt.AutoItX].Namespace

#[AutoIt.AutoItX].Assembly

#[AutoIt.AutoItX].BaseType

[AutoIt.AutoItX].Module

[AutoIt.AutoItX].DeclaredMembers | Where-Object {$_.name -like "Run"}

[AutoIt.AutoItX].DeclaredMethods | Where-Object {$_.name -like "Run"}

[AutoIt.AutoItX].DeclaredProperties

[AutoIt.AutoItX].DeclaredConstructors

[AutoIt.AutoItX].ImplementedInterfaces

[AutoIt.AutoItX].IsAbstract

[AutoIt.AutoItX].IsAnsiClass

[AutoIt.AutoItX].IsArray

[AutoIt.AutoItX].IsAutoClass

[AutoIt.AutoItX].IsAutoLayout

[AutoIt.AutoItX].IsByRef

[AutoIt.AutoItX].IsClass

[AutoIt.AutoItX].IsCOMObject

[AutoIt.AutoItX].IsInterface

[AutoIt.AutoItX].IsMarshalByRef

[AutoIt.AutoItX].IsPointer

[AutoIt.AutoItX].IsVisible

[AutoIt.AutoItX].TypeHandle


[AutoIt.AutoItX]::ClipPut("From AutoItX Assembly ! ")

$SRet = [AutoIt.AutoItX]::ClipGet()

write-host $SRet

Once we know the Data Types etc... we should be able to get this running using CLR correct ?

But unfortunately I did not get everything to work ... :(

;~  #AutoIt3Wrapper_UseX64=y
#include "CLR.Au3"

Example1()

Func Example1()
    Local $oAssembly = _CLR_LoadLibrary("C:\Program Files (x86)\AutoIt3\Beta\AutoItX\AutoItX3.Assembly.dll") ; Equals [Reflection.Assembly]::Loadfile()
    ConsoleWrite("!$oAssembly: " & IsObj($oAssembly) & @CRLF)

     Local $aText[] = ["We Love CLR !!"]

    local $oAu3X =_CLR_CreateObject($oAssembly,"AutoIt.AutoItX.ClipPut", CreateSafeArray($aText)) ; Equals [AutoIt.AutoItX]

    ConsoleWrite("!$oAu3X " & IsObj($oAu3X ) & @CRLF)
EndFunc

Example2()

Func Example2()
    Local $oAssembly = _CLR_LoadLibrary("C:\Program Files (x86)\AutoIt3\Beta\AutoItX\AutoItX3.Assembly.dll") ; Equals [Reflection.Assembly]::Loadfile()
    ConsoleWrite("$oAssembly: " & IsObj($oAssembly) & @CRLF)

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

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

    Local $aText[] = ["We Love AutoIt !!"]
    Local $sClipBoardText = ""

    $oAssemblyType.InvokeMember_3("", 0x158, 0, 0, 0, 0)

    $oAssemblyType.InvokeMember_3("ClipPut", 0x158, 0, 0, CreateSafeArray($aText), 0)
;~     ConsoleWrite("Clipboard Data: " & ClipGet() & @CRLF)
    MsgBox(0,"[AutoIt.AutoItX]::ClipPut" , "Clipboard Data: " & ClipGet())
    sleep (1000)
    ClipPut("AutoIt Rocks!!!")

    $oAssemblyType.InvokeMember_3("ClipGet", 0x158, 0, 0, 0, $sClipBoardText)
    ConsoleWrite("Clipboard Data: " & $sClipBoardText & @CRLF)
    MsgBox(0,"[AutoIt.AutoItX]::ClipPut" , "New Clipboard Data: " & $sClipBoardText)

EndFunc   ;==>Example

What is confusing (and especially for other users that are not familiar with CLR) is :

Sometimes you need to use the first method Example1 using _CLR_CreateObject and sometimes Example 2 ObjCreateInterface method ?

I hope that this Example gives you a good idea on how to debug the CLR.au3 

A lot of things have to do with Data Type conversion between CLR and Variant Types apparently...

Some useful information I found when reading the Python CLR implemenation... 

http://pythonnet.sourceforge.net/readme.html#installation

 

Edited by ptrex
Link to comment
Share on other sites

Also AHK tells it is not easy to get access to Static Methods in a straightforward way ?

It needs DllCalls inbetween ?

See this post and get to read the System.Math Examples at the bottom.

Quote

CLR_CreateObject is only for instantiating a class. Static methods like Math.Tan are difficult to call via COM as it requires...
[*:2252zeql]getting an instance of the Type object representing the type which contains the method,
[*:2252zeql]initializing a SAFEARRAY of VARIANTs containing parameters,
[*:2252zeql]calling the appropriate overload of Type.InvokeMember via a complicated DllCall, and
[*:2252zeql]interpreting the result VARIANT as necessary.For instance, this is a slightly modified (for readability) extract from CLR.ahk:


[color=darkgray]; pApp is a pointer to an AppDomain as returned by CLR_GetDefaultDomain()[/color]
p_App := COM_QueryInterface(pApp,"{05F696DC-2B29-3663-AD8B-C4389CF2A713}")
[color=darkgray]...[/color]
; Get typeof(Assembly) for calling static methods. (p_App->GetType()->Assembly->GetType())
DllCall(NumGet(NumGet(p_App+0)+40),"uint",p_App,"uint*",p_Type)
DllCall(NumGet(NumGet(p_Type+0)+80),"uint",p_Type,"uint*",p_Asm)
COM_Release(p_Type)
DllCall(NumGet(NumGet(p_Asm+0)+40),"uint",p_Asm,"uint*",p_Type)
COM_Release(p_Asm)

; Initialize VARIANTs & SAFEARRAY(VARIANT) for method args.
VarSetCapacity(vArg,16,0), NumPut(8,vArg), NumPut(psLib,vArg,8)
VarSetCapacity(vRet,16,0)
VarSetCapacity(rArgs,24,0), NumPut(1,NumPut(&vArg,NumPut(16,NumPut(1,rArgs))+4))

; Attempt to load from file.  (Call Assembly.LoadFrom().)
hr:=DllCall(NumGet(NumGet(p_Type+0)+228),"uint",p_Type
    ,"uint",COM_SysString(ws,"LoadFrom"),"int",0x118
    ,"uint",0,"int64",1,"int64",0,"uint",&rArgs,"uint",&vRet)

 

Edited by ptrex
Link to comment
Share on other sites

@ptrex:  interfaces I have tested with the examples and seems to work properly on my machine for the existing stuff. 

regarding autoit assembly did not know it exists so will study it.

Post 6 will nicely explain you from part 1-4 and inmore examples 5-8 how all this stuff works with Com. Then you will understand the logic of the calculation you see in AHK (and similar "magic" in AutoIt library).

will study your above post(s) later this week
 

 

Link to comment
Share on other sites

OK I will make the interface mods to the UDF and test it, see if it makes any difference.

Regarding the logic, I understand but when you run my example in post 185, it does not make sense !  

Something is not working correctly in the UDF so far... 

Let's see which conclusions it bring you...

Link to comment
Share on other sites

ptrex, Why do you think that creating an object as an instance of a class is the same as executing a static method which is not tied to an instance? I think it's obvious that these two different things should be implemented in two different ways.

Link to comment
Share on other sites

Hi Larsj, Sure these are 2 different things I understand. The confusing part is coming from my (maybe too much PowerShell life in the meantime)

Once you create an Object you have access to the Methods / Properties etc.

in the CLR UDF you can create an instance of the .NET Object but you don't have access to the Methods / Properties etc persé ...

Like this example it make sense you load the assembly, create and instance to the object and you can access Class Types / Methods / Properties / ....

Func Example_FileInfo()
  Local $oAssembly = _CLR_LoadLibrary( "mscorlib" )
  Local $oFileInfo = _CLR_CreateObject( $oAssembly, "System.IO.FileInfo", @ScriptDir & "\tst02.txt" )
  ConsoleWrite( "IsObj( $oFileInfo ) = " & IsObj( $oFileInfo ) & @CRLF & @CRLF)
  $oFileInfo.Create()
;~   ConsoleWrite( $oFileInfo.Name & @CRLF)
  MsgBox(0,"System.IO.FileInfo","File Created :  " & $oFileInfo.Name )
EndFunc

I would expect the same approach here : you load the Assembly, create and instance to the object .....

Func Example1()
    Local $oAssembly = _CLR_LoadLibrary("C:\Program Files (x86)\AutoIt3\Beta\AutoItX\AutoItX3.Assembly.dll") 
    ConsoleWrite("!$oAssembly: " & IsObj($oAssembly) & @CRLF)

     Local $aText[] = ["We Love CLR !!"]

    local $oAu3X =_CLR_CreateObject($oAssembly,"AutoIt.AutoItX.ClipPut", CreateSafeArray($aText)) 

    ConsoleWrite("!$oAu3X " & IsObj($oAu3X ) & @CRLF)
EndFunc

Of course the second example does not create and instance to the object for whatever reason ?

The only difference between these 2 assemblies that the 1st one is registered in the GAC and the second one is not ?

But the main difference is that the first one has a COM interface and the second one has not ;)

Edited by ptrex
Link to comment
Share on other sites

because AutoItX is not comvisible  [assembly: ComVisible(false)] whereas system.io.fileinfo  [ComVisible(true)]

system.io.fileinfo is not reachable by objCreate by progid as its not in registry

but most likely you can do objcreate with the clsid (i will try, and if that works thats a better approach to instantiate .NET ComVisible then createInstance)

And then it would be interesting to better understand what objCreateInterface is doing internally
as I think it then tries to provide the missing interfaces to make it COM compliant again.

And last few weeks reading a lot but not found a nice reference that easily explains the main difference between a .NET interface and a .COM interface and why they are not just 100% interchangable (I understand offcourse wrapping will cause performance degradation but for scripting thats is normally not terrible)

Even the COM examples show the normal CoCreateInstance call takes an IID_ImanagedInterface and internally the CCW stuff handles the magic

// Initialize COM and create an instance of the InterfaceImplementation class:
   CoInitialize(NULL);
   HRESULT hr = CoCreateInstance(CLSID_InterfaceImplementation,
               NULL, CLSCTX_INPROC_SERVER,
               IID_IManagedInterface, reinterpret_cast<void**>(&cpi));

 

Edited by junkew
missed the last part
Link to comment
Share on other sites

@ptrex Whats the question on this?  C# examples show static main so static methods just work 

Quote

 

Also AHK tells it is not easy to get access to Static Methods in a straightforward way ?

 

 

  • Example: .NET CLR Activator - GetType.au3 is incorrect as it should use system.activator interface definition thats to be made
  • Struggling with this example using safeArrayGetElement (incorrect parameter)
    HRESULT SafeArrayGetElement(  SAFEARRAY FAR* psa,   long FAR* rgIndices,   void FAR* pv );
     
    example()
    
    func example()
        Local $oAssCore = _CLR_LoadLibrary("mscorlib.dll")
        ConsoleWrite("  $oAssCore: " & IsObj($oAssCore) & @CRLF)
    
        local $tStr
        $oAssCore.get_ToString($tStr)
        ConsoleWrite("  $oAssCore.get_ToString: " & $tStr & @CRLF)
    
        local $vt ;~
        local $iCount=-1
        local $pVals
    
        local $pTypesArray
        $oAssCore.GetTypes($pTypesArray)
        $oAssCore.get_FullName($tStr)
        ConsoleWrite("  $oAssCore.get_FullName: " & $tStr & @CRLF)
    
    
    ; Access the safearray
    ;~  $result=SafeArrayAccessData($pTypesArray,$pVals)
    ;~  local $result
    ;~  consolewrite("result " & $result & @CRLF)
    
        SafeArrayGetUBound($pTypesArray, 1, $iCount)
        consoleWrite("Array elements " & $iCount & @CRLF)
        local $rgIndices[1]
        $rgindices[0]=1
    
    ;~  local $hr=SafeArrayGetElement($pTypesArray, $rgindices[0], $vt)
        local $hr=SafeArrayGetElement($pTypesArray, $rgindices[0], ptr($vt))
        consoleWrite($hr & " : Value  " & $VT & @CRLF)
    
    ;~  SafeArrayUnAccessData($pTypesArray)
    
    EndFunc

    Needs this in CLR.AU3 tag iassembly (so updating changing 3 lines)

    replace to : "get_ToString hresult(bstr*);" & _
    
    replace to : "get_FullName hresult(bstr*);" & _
        
    replace to : "GetTypes hresult(ptr*);" & _

    Needs these in safearray.au3

    ;~ SAFEARRAY* SafeArrayCreateVector(_In_ VARTYPE vt,  _In_ LONG    lLbound,  _In_ ULONG   cElements);
    Func SafeArrayCreateVector($vType, $ilBound, $cElements)
        Local $aRet  = DllCall("OleAut32.dll", "ptr", "SafeArrayCreateVector", "dword", $vType, "LONG", $ilBound, 'ULONG', $cElements)
        If @error Then Return SetError(1, 0, 0)
        Return $aRet[0]
    EndFunc
    ;~ HRESULT SafeArrayPutElement(  _In_ SAFEARRAY *psa,  _In_ LONG      *rgIndices,  _In_ void      *pv);
    Func SafeArrayPutElement($pSA, $rgIndices, $pv)
        Local $aRet = DllCall("OleAut32.dll", "long", "SafeArrayPutElement", "ptr", $pSA, "LONG", $rgIndices, 'ptr', $pv)
        If @error Then Return SetError(1, 0, 0)
        Return $aRet[0]
    EndFunc
    ;~ HRESULT SafeArrayGetElement(  _In_  SAFEARRAY *psa,  _In_  LONG      *rgIndices,  _Out_ void      *pv);
    Func SafeArrayGetElement($pSA, $rgIndices, ByRef $pv)
    ;~  If its a single dimension then we get an integer and not an array
        if not isarray($rgIndices) then
            local $tArr[1]
            $tArr[0]=$rgIndices
            Local $aRet = DllCall("OleAut32.dll", "long", "SafeArrayGetElement", "ptr", $pSA, "long*", $tArr[0], 'uint_ptr*', $pv)
        Else
            Local $aRet = DllCall("OleAut32.dll", "long", "SafeArrayGetElement", "ptr", $pSA, "long*", $rgIndices, 'uint_ptr*', $pv)
        EndIf
    
        If @error Then Return SetError(1, 0, 0)
        $pv = $aRet[3]
        Return $aRet[0]
    EndFunc

     

 

Edited by junkew
updated 3 functions for safearray.au3
Link to comment
Share on other sites

@junkew                        

Changes:

I tested the Modification to the UDF function you proposed in post 183, and everything still works... So I will post a Version v2 in the other thread.

Together with the AutoIt.AutoItX Custom Assembly Example of ClipPut(), and the modified  .NET CLR Activator - GetType.au3 Example.

Clarifications :

Thanks a lot for the clarification on the different methods to use. In fact that is what I figured out last evening after I posted the examples in post 189 ...

Just for the record, basically you can say that :

COM Visible .NET Assemblies is called using _CLR_CreateObject() / comparable to Conventional COM object are called using ObjCreate()

Non COM Visible .NET Assemblies is called using ObjCreateInterfaceInvokeMember / comparable to WinAPI Libr. using DLLCall()

But this brings us to some more Questions : 

Why the ClipPut() works and the ClipGet() does not ?

Func Example2()
    Local $oAssembly = _CLR_LoadLibrary("C:\Program Files (x86)\AutoIt3\Beta\AutoItX\AutoItX3.Assembly.dll") ; Equals [Reflection.Assembly]::Loadfile()
    ConsoleWrite("$oAssembly: " & IsObj($oAssembly) & @CRLF)

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

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

    Local $aText[] = ["We Love AutoIt !!"]
    Local $sClipBoardText = ""

    $oAssemblyType.InvokeMember_3("", 0x158, 0, 0, 0, 0)

    $oAssemblyType.InvokeMember_3("ClipPut", 0x158, 0, 0, CreateSafeArray($aText), 0)
;~     ConsoleWrite("Clipboard Data: " & ClipGet() & @CRLF)
    MsgBox(0,"[AutoIt.AutoItX]::ClipPut" , "Clipboard Data: " & ClipGet())
    sleep (1000)
    ClipPut("AutoIt Rocks!!!")

    $oAssemblyType.InvokeMember_3("ClipGet", 0x158, 0, 0, 0, $sClipBoardText) ; <===== DOES NOT WORK
    ConsoleWrite("Clipboard Data: " & $sClipBoardText & @CRLF)
    MsgBox(0,"[AutoIt.AutoItX]::ClipPut" , "New Clipboard Data: " & $sClipBoardText)

EndFunc   ;==>Example

Did I make a mistake or is there still bug in the UDF or is it because it can't reach the data outside of the au3 Process or ...

I am still trying to understand where things go wrong if they don't work as expected ...

The same thing happened if I use the RUN("Notepad.exe") method in the AutoItX assembly, nothing happens...

I was refering to the AHK simple example that was givin me issues too ?

Using the COM Visible Class Math, trying to get a simple "Math.PI" returned did not work... But I will look into this again... could be that I made a mistake somewhere.

So there are still bits and pieces that puzzle me, whereas this is working straight forward in PowerShell (this is my only benchmark at the moment).

So it's hard for me with out have all the under the hood documentation to pinpoint where it goes wrong...

Link to comment
Share on other sites

Quote

COM Visible .NET Assemblies is called using _CLR_CreateObject() / comparable to Conventional COM object are called using ObjCreate()

Non COM Visible .NET Assemblies is called using ObjCreateInterfaceInvokeMember / comparable to WinAPI Libr. using DLLCall()

N.B. Wouldn't it make sense to name the function _CLR_ObjCreate so it is in line with ObjCreate and ObjCreateInterface?

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

Ops, this tells you that I didn't carefully read all 190 posts in this thread before posting myself ;)

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

and after .net 2.0-4.7 we are back at coreclr with c-flat api's

If you follow all sourcerepositories and scan them a lot boils really down to CoCreateInstance that is also used in objCreate/objCreateInterface so will raise issue in AutoIt issue log to rename the AutoIt functions to CoCreateInstance :D. I don't care how we call them but if we have 3 then it should be clearly documented when and why to use any of them (or make a new function that wraps away the difference between the 3). For me thats still a mystery (after all posts in this thread and all manuals etc which was fun to read and learn) and I am trying to find out first for MSCORLIB and MSCOREE.

  • For objCreateInterface we should ask Jon or other developers whats the reason its still BETA as in this thread we also have examples that are based on objCreateInterface whereas some of them would be logical to write with CLR_CreateObject (calling createInstance methods)
Link to comment
Share on other sites

@ptrex

not behind a computer with AutoIt but try this

Local $sClipBoardText = ["Now I am an array of text"]

The clipboard types you have to manage and as you put text on it as an array of characters it seems logical to assume you have to make it type array (and internally stuff with SAFEARRAY to array will be handled assumming that AutoIt internally has not SAFEARRAY but "normal"  c/c++ array). Could also be you have to make your variable preinitialized with a certain length of spaces / NULL values.

Link to comment
Share on other sites

@junkew                                 

Thanks but it's the opposite side that does not work. The ClipPut() is OK, it is the ClipGet() from a regular clipboard value that does not work ... 

But no hurries. I will release only the AutoIt.AutoItX.ClipPut() for now... 

For the   .NET CLR Activator - GetType.au3 correction, I could not find the interface type in the UDF.au3, so that has to wait as well...

Link to comment
Share on other sites

2002

initial way of coding with cocreateinstance and c# example system.activator

https://www.codeproject.com/Articles/2615/DirectShow-NET

System.activator looks com visible so no clue why we cannot do objcreate with clsid. Progid is logical as its not registered as system.activator

://msdn.microsoft.com/en-us/library/system.activator.aspx

 

The answer regarding System.Activator looks to be in mscorlib_TLB.pas (Google for it)

IID__Activator: TGUID = '{03973551-57A1-3900-A2B5-9083E3FF2943}';
  CLASS_Activator: TGUID = '{9BA4FD4E-2BC2-31A0-B721-D17ABA5B12C3}';
...
  IID__ApplicationActivator: TGUID = '{D1204423-01F0-336A-8911-A7E8FBE185A3}';
...
 IID_IActivator: TGUID = '{C02BBB79-5AA8-390D-927F-717B7BFF06A1}';
 ...
 CLASS_ApplicationActivator: TGUID = '{1D09B407-A97F-378A-ACCB-82CA0082F9F3}';
 ...
 // Constants for enum ActivatorLevel
type
  ActivatorLevel = TOleEnum;
const
  ActivatorLevel_Construction = $00000004;
  ActivatorLevel_Context = $00000008;
  ActivatorLevel_AppDomain = $0000000C;
  ActivatorLevel_Process = $00000010;
  ActivatorLevel_Machine = $00000014;
 ...
   _Activator = interface;
  _AccessViolationException = interface;
  _AccessViolationExceptionDisp = dispinterface;
  _ApplicationActivator = interface;
  _ApplicationActivatorDisp = dispinterface;
  ...
    IActivator = interface;
  IActivatorDisp = dispinterface;
  ...
// *********************************************************************//
// Declaration of CoClasses defined in Type Library                       
// (NOTE: Here we map each CoClass to its Default Interface)              
// *********************************************************************//
  CLRException = _Exception;
  Activator = _Activator;
  ....
  // *********************************************************************//
// Interface: IActivator
// Flags:     (4416) Dual OleAutomation Dispatchable
// GUID:      {C02BBB79-5AA8-390D-927F-717B7BFF06A1}
// *********************************************************************//
  IActivator = interface(IDispatch)
    ['{C02BBB79-5AA8-390D-927F-717B7BFF06A1}']
    function Get_NextActivator: IActivator; safecall;
    procedure _Set_NextActivator(const pRetVal: IActivator); safecall;
    function Activate(const msg: IConstructionCallMessage): IConstructionReturnMessage; safecall;
    function Get_level: ActivatorLevel; safecall;
    property NextActivator: IActivator read Get_NextActivator write _Set_NextActivator;
    property level: ActivatorLevel read Get_level;
  end;

// *********************************************************************//
// DispIntf:  IActivatorDisp
// Flags:     (4416) Dual OleAutomation Dispatchable
// GUID:      {C02BBB79-5AA8-390D-927F-717B7BFF06A1}
// *********************************************************************//
  IActivatorDisp = dispinterface
    ['{C02BBB79-5AA8-390D-927F-717B7BFF06A1}']
    property NextActivator: IActivator dispid 1610743808;
    function Activate(const msg: IConstructionCallMessage): IConstructionReturnMessage; dispid 1610743810;
    property level: ActivatorLevel readonly dispid 1610743811;
  end;

And this is then the part where the example is on instantiating the class in delphi (seems in the end then to use com function)

// *********************************************************************//
// The Class CoActivator provides a Create and CreateRemote method to          
// create instances of the default interface _Activator exposed by              
// the CoClass Activator. The functions are intended to be used by             
// clients wishing to automate the CoClass objects exposed by the         
// server of this typelibrary.                                            
// *********************************************************************//
  CoActivator = class
    class function Create: _Activator;
    class function CreateRemote(const MachineName: string): _Activator;
  end;

// *********************************************************************//
// The Class CoAppDomain provides a Create and CreateRemote method to          
// create instances of the default interface _AppDomain exposed by              
// the CoClass AppDomain. The functions are intended to be used by             
// clients wishing to automate the CoClass objects exposed by the         
// server of this typelibrary.                                            
// *********************************************************************//
  CoAppDomain = class
    class function Create: _AppDomain;
    class function CreateRemote(const MachineName: string): _AppDomain;
  end;
class function CoActivator.Create: _Activator;
begin
  Result := CreateComObject(CLASS_Activator) as _Activator;
end;

 

Edited by junkew
more info on activator
Link to comment
Share on other sites

updated post 199 with info on how to be able to create a object for System.Activator

Based on this I understand a little more but COM is not my native area.

Search for Activator in this source and it gets a little clearer

https://sourceforge.net/p/whitestaruml/code-0/270/tree/trunk/Imports/mscorlib_TLB.pas

As _Activator is hidden (and I assume its missing iDispatch) we have to do something similar with ObjCreateInterface or if it works like delphi it can just be a objcreate

 

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