Jump to content

Recommended Posts

Posted

Basically all docs and links say

// Call the method via late binding. 
  // The parameter is passed by reference (VT_BSTR | VT_BYREF)
  obj.GetType().InvokeMember("SomeMethod", BindingFlags.InvokeMethod, null,
   obj, args, mods, null, null);

But when we have returned generic collection $pscollection i am unable to invokemember tostring or count or ...

 

Posted

You can try to ask this guy Lexikos in the AutoHotkey forum. In post 94 there is an example in ahk code that illustrates the problem.

Posted

Thanks for the suggestion... but I will drop it for now and move on... 

Later this week or next week, I will publish in the final release thread what we have up till now. And also make a thread in the PowerShell section of the forum.

Everything works to my expectation, except for the output of PSOBJECTS members to Console... 

Posted (edited)

Good suggestion I will sign in in that forum to (never used AHK).

Over time people will do more nice tricks in bridging AutoIt with .NET for me its easier in C# to understand how to handle this then doing the same in AutoIt.

  • Someone over time will find out how to do MSIL directly with either CLR.AU3 or DOTNET.AU3
    As you can see in below MSIL part is System.Type.GetTypeFromHandle an important one to get the type of an instance
Icall       System.Type.GetTypeFromHandle
callvirt    System.Collections.Generic.Dictionary<System.Type,System.Reflection.PropertyInfo[]>.ContainsKey
brfalse.s   IL_002F
ldarg.0     
ldfld       elementProperties
ldtoken     01 00 00 1B 
call        System.Type.GetTypeFromHandle
callvirt    System.Collections.Generic.Dictionary<System.Type,System.Reflection.PropertyInfo[]>.get_Item
pop         
br.s        IL_0053
ldarg.0     
ldfld       elementProperties
ldtoken     01 00 00 1B 
call        System.Type.GetTypeFromHandle
ldtoken     01 00 00 1B 
call        System.Type.GetTypeFromHandle
call        System.Type.GetProperties
callvirt    System.Collections.Generic.Dictionary<System.Type,System.Reflection.PropertyInfo[]>.set_Item
  • ; Equivalent to GetType(TimeSpan)
    L_001d: ldtoken [mscorlib]System.TimeSpan
    L_0022: call [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle([mscorlib]System.RuntimeTypeHandle)
    
    ; This is the late-binding way of creating an empty TimeSpan.
    L_0027: call object [mscorlib]System.Activator::CreateInstance([mscorlib]System.Type)
    L_002c: unbox [mscorlib]System.TimeSpan
    L_0031: ldobj [mscorlib]System.TimeSpan
    L_0036: stloc.2

    Its just a matter of understanding where C# compiler is dealing a lot of things directly in AutoIt you have to call all the reflection and compiler stuff yourself.

  • Very interesting material but timeconsuming to read and tryout.
  • All bits and pieces have been hit in this thread and no reason to believe that it cannot be done.

So now and then I study this and spent some hours trying in AutoIt but must admit its so much easier in a visual studio debugging environment to understand then with dozens of consolewrites, etc.. I am learning a lot also from the CLR runtime last few months but its just a hobby and not a fulltime job ;-) 

 

Edited by junkew
Posted

If you want to study more on this topic. 

This is some more interesting reading on the ins and outs of .NET  CLR: 

https://www.codeproject.com/articles/20481/net-type-internals-from-a-microsoft-clr-perspecti  

Objects are discussed here :

Quote

The variable referring to an instance of a Reference Type is called Object Reference and is a pointer to the starting address of Reference Type instance + 4 bytes. The starting address of any Reference Type instance is a 4 byte value called sync block address and points to a location in a process-wide table that contains structures used for synchronizing access to instances of Reference Types. The next 4 bytes contains the address of a memory (AppDomain specific) that contains a structure holding the Method Table of the Reference Type for which the object is instantiated or points to. This Method Table in turn contains a reference to another structure, which holds the Runtime Type Information of the corresponding Reference Type.

This is the complete CLR interfacing documentation : 

https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/hosting/clr-hosting-interfaces

But to end here with my latest findings :

If you uncomment the For $Item in  $objPsCollection  / Next part to loop through the members. 

You will notice that the script will NOT execute anymore the Switch command.

$objPsCollection = $pObjectPS.EndInvoke($objAsync)

;~  For $Item in  $objPsCollection
;~      ConsoleWrite($Item.members.value("ID")
;~  Next

    Switch $iOutput
            Case 0
;~              ConsoleWrite( $objPsCollection & @CRLF)
                MsgBox(16,"PSHost","Output To Console is not working yet :-( ?" & @CRLF &  @CRLF & " Best make a different OUTPUT option.")
            Case 1
                Sleep(10000)
;~              WinWaitClose("")
            Case 3
                MsgBox(0,"PSHost","File Output Ready on Desktop.")
        EndSwitch

This means that in some way the For / Next  leaves the script and is never returned ? 

That's why there's no ConsoleWrite feedback to the host. It finds the members and the loop works as you see while it takes the time it takes to loop.

But this happens somewhere else , the reason WHY this happens is not clear. Does it have anything to do with MTA state the PowerShell runs in ? or something else this is not clear.

I hope this can give some hints in getting a clue what is going on...

Anyhow we are now 6 months further down the road with .NET CLR and I am very happy with the results !

Even if the CLR code is messy, I would not change a lot to it. It works apart from this ConsoleWrite  Host part of it...

I will now focus more on applying the CLR / PowerShell, rather then tryng to figure out how it works.

If I run into something interesting I will still add stuff to this thread of course if it can help ...

 

 

 

Posted

thx. more to read :ILA3:

I was not able to do anything on the 

$objPsCollection

It just dies AutoIt script whenever I try

consolewrite($objPsCollection.ToString()) 
consolewrite($objPsCollection.Count())

or

consolewrite($myType.Invokemethod("ToString",.....)) 
consolewrite($myType.Invokemethod("Count",.....))

I assume as its not comvisible AutoIt tries to do a QueryInterface which not exist(s) on all .NET objects (and should be reached then thru System.___Object interface logic where i do not have a clue on how to reach that in AutoIt so coming days will try out what dotnet.au3 is doing or try things in this thread with clr.AHK to see it in that library the concept on .net generic collections is working).

So somehow on the $PSCollection its not creating the object methods reachable.

And suppose $PSCollection is a pointerreference to an object then with below stuff I could make the ObjCreateInterface (just like @Danyfirex did for other base interfaces when we started this thread)

struct __declspec(uuid("65074f7f-63c0-304e-af0a-d51741cb4a8d"))
_Object : IDispatch
{
    //
    // Raw methods provided by interface
    //

      virtual HRESULT __stdcall get_ToString (
        /*[out,retval]*/ BSTR * pRetVal ) = 0;
      virtual HRESULT __stdcall Equals (
        /*[in]*/ VARIANT obj,
        /*[out,retval]*/ VARIANT_BOOL * pRetVal ) = 0;
      virtual HRESULT __stdcall GetHashCode (
        /*[out,retval]*/ long * pRetVal ) = 0;
      virtual HRESULT __stdcall GetType (
        /*[out,retval]*/ struct _Type * * pRetVal ) = 0;
};

https://stackoverflow.com/questions/1233468/unable-to-cast-com-object-of-type-exception

 

 

  • 3 years later...

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
×
×
  • Create New...