Jump to content

Using .NET libary with AutoIt, possible?


Recommended Posts

Hi all,

I will update the following in release v3.0 

- CLR Change GetMembers Tag (info post 237 Danyfirex)

- Added SafeArrayGetElement (info post 235 Junkew)

- Add changes SafeArrayAccessData  & SafeArrayUnAccessData  in Examples (info post 238 Larsj)

- Add Example GetTypes and GetMembers (post 233 - 237 Danyfirex)

- Add Example Run EXE from Memory (post 228 Danyfirex)

Junkew,

I will do the Arrays update in a next release if everyone agrees, because this is quite a script breaking change ....

Again thanks a lot for these great additions !!

I am still surprised about the speed of the scripts, so far it runs smooth ...

Edited by ptrex
Link to comment
Share on other sites

two things.

1.- My nick is Danyfirex just one n :P

2.- You're missing you from Developers  and credits. ;)

 

Saludos

 

Link to comment
Share on other sites

Correct, Sorry I missed that ... :( 

Not so important that my name in the spotlight .... I am already homered to be in the middle of you smart guys !

More like a moderator to keep everything going and coordinating ...

While we have now developed quite some advanced functions and Examples...

We are still lacking simple examples which everyone can recognize that are familiar with .Net Base Classes or PowerShell functionality...

So we need to come up with some more practical use cases, that can interest the wide audience...

I will think it over during my holidays... ( any input you guys is welcome too ...)

 

Link to comment
Share on other sites

Example idea(s) (will add more over time):  

Edited by junkew
Link to comment
Share on other sites

Hi All, I am back.

Thanks for posting the documentation ... 

Many things are possible indeed with .NET CLR

I would recommend before further going into anymore depth. To just provide some simple examples and use cases that everyone can understand...?

Like this :

_Example1()

Func _Example1()

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

    local $objFileInfoClass =_CLR_CreateObject($oAssembly,"System.IO.FileInfo", @ScriptFullPath )
    ConsoleWrite("!$oRnd " & IsObj($objFileInfoClass) & @CRLF)

    MsgBox(0,".Net CLR System.IO.File #", "FileAttributes # : " & @ScriptFullPath & @CRLF)

    $Attributes = $objFileInfoClass.Attributes ;  Gets or sets the attributes for the current file or directory. (Inherited from FileSystemInfo.)
        ConsoleWrite("$Attributes: " & $Attributes & @CRLF)

    $CreationTime = $objFileInfoClass.CreationTime ;  Gets or sets the creation time of the current file or directory. (Inherited from FileSystemInfo.)
        ConsoleWrite("$CreationTime: " & DateStringToDateTime_EU($CreationTime) & @CRLF)


    $objDirectory = $objFileInfoClass.Directory ;  Gets an instance of the parent directory.
        ConsoleWrite("$objDirectory: " & $objDirectory & @CRLF)

    $DirectoryName = $objFileInfoClass.DirectoryName ;  Gets a string representing the directory's full path.
        ConsoleWrite("$DirectoryName: " & $DirectoryName & @CRLF)

    $Exists = $objFileInfoClass.Exists ;  Gets a value indicating whether a file exists. (Overrides FileSystemInfo.Exists.)
        ConsoleWrite("$Exists: " & $Exists & @CRLF)

    $Extension = $objFileInfoClass.Extension ;  Gets the string representing the extension part of the file. (Inherited from FileSystemInfo.)
        ConsoleWrite("$Extension: " & $Extension & @CRLF)

    $FullName = $objFileInfoClass.FullName ;  Gets the full path of the directory or file. (Inherited from FileSystemInfo.)
        ConsoleWrite("$FullName: " & $FullName & @CRLF)

    $IsReadOnly = $objFileInfoClass.IsReadOnly ;  Gets or sets a value that determines if the current file is read only.
        ConsoleWrite("$IsReadOnly: " &  $IsReadOnly& @CRLF)

    $LastAccessTime = $objFileInfoClass.LastAccessTime ;  Gets or sets the time the current file or directory was last accessed. (Inherited from FileSystemInfo.)
        ConsoleWrite("$LastAccessTime: " & DateStringToDateTime_EU($LastAccessTime) & @CRLF)


    $LastWriteTime = $objFileInfoClass.LastWriteTime ;  Gets or sets the time when the current file or directory was last written to. (Inherited from FileSystemInfo.)
        ConsoleWrite("$LastWriteTime: " & DateStringToDateTime_EU($LastWriteTime) & @CRLF)


    $Length = $objFileInfoClass.Length ;  Gets the size, in bytes, of the current file
        ConsoleWrite("$Length: " & $Length & @CRLF)

    $Name = $objFileInfoClass.Name ;  Gets the name of the file. (Overrides FileSystemInfo.Name.)
        ConsoleWrite("$Name: " & $Name & @CRLF)
EndFunc   ;==>_Example1

Func DateStringToDateTime_EU($dtmDate)
    Return(StringRegExpReplace($dtmDate, "\A(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(?:.*)","$1/$2/$3 $4:$5:$6"))
EndFunc

Func DateStringToDateTime_US($dtmDate)
    Return(StringRegExpReplace($dtmDate, "\A(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(?:.*)","$2/$3/$1 $4:$5:$6"))
EndFunc

This way anyone can understand what the .NET CLR has to offer... and start building up experience.

It would be nice to start building an example library with all this kind of use cases examples over the different mscorlib Classes

Once we have more users on board we can start taking it one step further... ?

Link to comment
Share on other sites

Hi all,

Anyone still alive on the other side of the internet ... :)

Example()

Func Example()
  Local $oAssembly = _CLR_LoadLibrary( "System" )

  ; Get an instance of the System Up Time performance counter.
  Local $Uptime = _CLR_CreateObject( $oAssembly, "System.Diagnostics.PerformanceCounter", "System", "System Up Time", "")
  ConsoleWrite( "IsObj( Test ) = " & IsObj( $Uptime ) & @CRLF & @CRLF)

  ; Two read counter.
    $Uptime.NextValue();
    Local $nSecs =$Uptime.NextValue()
    $Uptime.Close()

    MsgBox(0,"System Up Time", Round($nSecs / 3600) & " Hours or " & Round($nSecs /60)& " Minutes or " & Round($nSecs) & " Seconds")

EndFunc

 

Link to comment
Share on other sites

To much to read and to many classes to make examples for

  • Not sure if we already have other AU3 UDF's dealing with cryptographic stuff: 
    System.Security.Cryptography classes look nice
  • these beauties just available thru objcreate so no need for clr.au3
    hashtable is nice as its possible to do maps that is still in beta
    bitarray is nice but I have no use for it
objCreate   =   1   clr =   1   $sFullName  =   System.Collections.Queue
objCreate   =   1   clr =   1   $sFullName  =   System.Collections.ArrayList
objCreate   =   0   clr =   1   $sFullName  =   System.Collections.BitArray
objCreate   =   1   clr =   1   $sFullName  =   System.Collections.Stack
objCreate   =   1   clr =   1   $sFullName  =   System.Collections.Hashtable
objCreate   =   1   clr =   1   $sFullName  =   System.Collections.SortedList
  • changed .NET Access Native MSCorLib Classes - GetTypes.au3 to also give back if same object was creatable thru objcreate to make above small list
Func Example1()
    Local $oErrorHandler = ObjEvent("AutoIt.Error", "_ErrFunc")
    Local $oType = _CLR_LoadLibrary("mscorlib")
    ConsoleWrite("$oType: " & IsObj($oType) & @CRLF)

    Local $pTypes
    $oType.GetTypes($pTypes)

    Local $iDim = SafeArrayGetDim($pTypes)
    ConsoleWrite("$iDim = " & $iDim & @CRLF)

    Local $iLBound, $iUBound
    SafeArrayGetLBound($pTypes, 1, $iLBound)
    SafeArrayGetUBound($pTypes, 1, $iUBound)
    ConsoleWrite("$iLBound = " & $iLBound & @CRLF)
    ConsoleWrite("$iUBound = " & $iUBound & @CRLF)

    Local $tTypeArray = DllStructCreate($tagSAFEARRAY, $pTypes)
        Local $iPtrSize=(DllStructGetData($tTypeArray, "cbElements"))

    ConsoleWrite(".cDims = " & (DllStructGetData($tTypeArray, "cDims")) & @CRLF & @CRLF)
    ConsoleWrite(".fFeatures = 0x" & Hex(DllStructGetData($tTypeArray, "fFeatures")) & @CRLF & @CRLF)
    ConsoleWrite(".cbElements = " & $iPtrSize & @CRLF & @CRLF)

    Local $vt=0
    SafeArrayGetVartype($pTypes, $vt)
    ConsoleWrite("$vt = " & $vt  & @CRLF & @CRLF)

;~  Local $tGUID = $tagGUID
;~  Local $tGUID = DllStructCreate($tagGUID, $pTypes - 16)
;~  Local $sGUID = _WinAPI_StringFromGUID($tGUID)
;~  ConsoleWrite("$sGUID = " & $sGUID & @CRLF)

    Local $pTypeArrayData = 0
    Local $tType=0
    Local $pType=0
    Local $oType=Null
    Local $oType2=Null
    Local $sFullName=""

    SafeArrayAccessData($pTypes, $pTypeArrayData)
      For $i = 0 To $iUBound
;~         SafeArrayAccessData($pTypes, $pTypeArrayData)
        $tType = DllStructCreate("ptr", $pTypeArrayData + ($i * $iPtrSize))
        $pType = DllStructGetData($tType, 1)
;~         ConsoleWrite("+$pType = " & $pType & @CRLF)
;~         SafeArrayUnaccessData($pTypes)

        $oType = ObjCreateInterface($pType, $sIID_IType, $sTag_IType)
;~         ConsoleWrite("IsObj( $oType ) = " & IsObj($oType) & @CRLF)

        $oType.get_FullName($sFullName)
;~      See if we also can get object thru objcreate
            $oType2=objcreate($sFullName)
            
            ConsoleWrite("objCreate = ;" & IsObj($oType2) & "; clr = ;" & IsObj($oType) & "; $sFullName = ;" & $sFullName & @CRLF )
;~      endIf
        $sFullName=""
        $pType= 0
        $tType=0
        $oType = Null
      Next
    SafeArrayUnaccessData($pTypes)

EndFunc   ;==>Example1

Func _ErrFunc($oError)
endfunc
  • And these are the workaround solutions for some frequently used win32 structs (no clue how to pass our own structs)
System.Runtime.InteropServices.WindowsRuntime.Point
System.Runtime.InteropServices.WindowsRuntime.Size
System.Runtime.InteropServices.WindowsRuntime.Rect
  • And this we have to study to make some dynamic objects
     
System.Runtime.InteropServices.Expando.IExpando
  • and date time
System.DateTime

 

Link to comment
Share on other sites

Yes we know this a long time already, that some objects in .NET are exposed as conventional COM objects.

CLR : See .NET Enum Classes.au3 example. This will exactly the same list as your analysis report. ;)

Like for Example

CreateObject( "System.Random" )

Anyhow It is a good finding of you that we can start mixing CLR Objects with conventional COM objects in 1 function :) 

This opens some new potentials !

I will try to post a system date example soon...

Edited by ptrex
Link to comment
Share on other sites

For Each of the examples in CLR.NET Access Native MSCorLib Classes2 .au3

;#AutoIt3Wrapper_UseX64=y

#include "CLR.au3"

Random1()

; CLR Approach
Func _Example1()
    Local $oAssembly = _CLR_LoadLibrary("mscorlib")
    ConsoleWrite("!$oAssembly: " & IsObj($oAssembly) & @CRLF)

    local $oRnd =_CLR_CreateObject($oAssembly,"System.Random")
    ConsoleWrite("!$oRnd " & IsObj($oRnd) & @CRLF)

    MsgBox(0,".Net CLR Random #", "System.Random # : " & $oRnd.Next_2( 1, 100 ) & @CRLF)

EndFunc

Random2()

; COM Approach
Func Random2()

    $objRandom = ObjCreate( "System.Random" )
    MsgBox(0,"System.Random" , $objRandom.Next_2( 1, 100 ))
EndFunc

We can add the same Conventional COM examples if you like ?

Edited by ptrex
Link to comment
Share on other sites

Sure, agree.

But it is more confusing for the users to know when to use which approach... So best we let them decide, and show in the Examples that there are 2 ways (in some cases).

We can add your analysis function together with my Example to show this to them on how to use it.

 

 

 

Link to comment
Share on other sites

Link to comment
Share on other sites

No Success with System.DateTime ?

But I got the System.Int32 and Double in the meantime....

Example1()

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

    ; Create Int32 Object
    Local $pAssemblyType = 0
    $oAssembly.GetType_2("System.Int32", $pAssemblyType)
    ConsoleWrite("$pAssemblyType = " & Ptr($pAssemblyType) & @CRLF)

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

    Local $aText[] = ["12"]
    Local $pObject1 = 0
    $oActivatorType.InvokeMember_3("Parse", 0x158, 0, 0, CreateSafeArray($aText), $pObject1)

    ConsoleWrite("Int32 : " & $pObject1 & @CRLF & @CRLF)


    ; Create Double Object
    Local $pAssemblyType = 0
    $oAssembly.GetType_2("System.Double", $pAssemblyType)
    ConsoleWrite("$pAssemblyType = " & Ptr($pAssemblyType) & @CRLF)

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

    Local $aText[] = ["1212,55"]
    Local $pObject = 0
    $oActivatorType.InvokeMember_3("Parse", 0x158, 0, 0, CreateSafeArray($aText), $pObject)

    ConsoleWrite("Double : " & $pObject & @CRLF & @CRLF)


    ; Create DateTime Object
    Local $pAssemblyType = 0
    $oAssembly.GetType_2("System.DateTime", $pAssemblyType)
    ConsoleWrite("$pAssemblyType = " & Ptr($pAssemblyType) & @CRLF)

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

    Local $pObject = 0
    $oActivatorType.InvokeMember_3("Year", 0x158, 0, 0, 0, $pObject)

    ConsoleWrite("DateTime : " & $pObject & @CRLF & @CRLF)

EndFunc

 

Link to comment
Share on other sites

Try this.

$oActivatorType.InvokeMember_3("Now", 4096, 0, 0, 0, $pObject)

 

Saludos

 

Link to comment
Share on other sites

We should discuss some coding conventions on how to write it

; Create Int32 Object
    Local $pAssemblyType = 0
    $oAssembly.GetType_2("System.Int32", $pAssemblyType)
    ConsoleWrite("$pAssemblyType = " & Ptr($pAssemblyType) & @CRLF)

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

    Local $aText[] = ["12"]
    Local $pObject1 = 0
    $oActivatorType.InvokeMember_3("Parse", 0x158, 0, 0, CreateSafeArray($aText), $pObject1)

    ConsoleWrite("Int32 : " & $pObject1 & @CRLF & @CRLF)

I suggest to write as (but open for other thoughts/opinions)

; Create Int32 Object
    Local $pInt32Type = 0
    $oAssembly.GetType_2("System.Int32", $pInt32Type)
    ConsoleWrite("$pInt32Type = " & Ptr($pInt32Type) & @CRLF)

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

    Local $aText[] = ["12"]
    Local $tValue = 0
    $oInt32.InvokeMember_3("Parse", 0x158, 0, 0, CreateSafeArray($aText), $tValue)

    ConsoleWrite("Int32 : " & $tValue & @CRLF & @CRLF)
  • maybe $p<someething>type just write $t<something> as $t indicates its type
  • maybe $o<something> as that just indicaties with $o its an object reference

And somehow I have the feeling the dot syntax like $oInt32.Parse we should be able to get working but no clue yet how

edit: 
this works for a property so í assume I should also be able to get the COM object itself to use dot syntax. 

https://msdn.microsoft.com/en-us/library/system.reflection.typeinfo.getdeclaredproperty(v=vs.110).aspx

Edited by junkew
Link to comment
Share on other sites

Hi Junkew,

Fully agree, these are just trial and errors I through in the air...

All of this is testing material and not meant to be having any final coding best practices... I just copy code from here and there to speed up the process.

In fact the whole CLR.au3 and examples need a lot of cleanup and review... but that's for later. 

I have the feeling that indeed we are over complicating sometime our efforts to come to some results.

If you see how many lines we have to write for such a simple Method. This approach would look making more sense...

$objYear = _CLR_CreateObject($oAssembly, 'System.Int32')

$objYear.parse("12")

Having DOT syntax is one of the main improvements we should look for.

Second thing I am struggling with in our coding examples is the SafeArray stuff.

That in my opinion should be handled in the background instead of in the front end script.

Also I saw that there are multiple ways to ROME !

The same result of the System.Int32 can be obtained like this ? Not sure what the difference is ?

Example1()

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

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

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

    ; Create a System.Int32 or System.Double Object
    Local $aText[] = ["mscorlib", "System.Int32"] 
    Local $pObject = 0
    $oActivatorType.InvokeMember_3("CreateInstance", 0x158, 0, 0, CreateSafeArray($aText), $pObject)
    ConsoleWrite("IsObject: " & IsObj($pObject) & @TAB & "System.Int32: " & $pObject & @CRLF)
  
  Endfunc

Anyhow I will do the clean up ones we have enough gather together. And also do some restructuring of the Examples published in a more logical way, no problem... 

Main focus now is to go wide in terms of generating as many working examples as possible. 

PS : if you see the time to do rewriting and cleanup, please do I don't mind...

Link to comment
Share on other sites

Hi Danyfirex,

Still no go :(

Example1()

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

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

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

    ; Create a System.DateTime
    Local $aText[] = ["mscorlib", "System.DateTime"]
    Local $pObject = 0
    $oActivatorType.InvokeMember_3("Now", 4096, 0, 0, 0, $pObject)
    ConsoleWrite("IsObject: " & IsObj($pObject) & @TAB & "$pObject: " & $pObject & @CRLF)
Endfunc

 

Link to comment
Share on other sites

I got also an other issue... 

This example returns an Array result list.

Example()

Func Example()
    Local $oAssembly = _CLR_LoadLibrary("System")
    ConsoleWrite("$oAssembly: " & IsObj($oAssembly) & @CRLF)

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

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

    Local $strProcName[] = ["Notepad"]
    Local $pObject = 0
    $oAssemblyType.InvokeMember_3("GetProcessesByName", 0x158, 0, 0,CreateSafeArray($strProcName), $pObject); $oAssemblyType.GetProcessesByName($strProcName)
    ConsoleWrite("Array : " & Isobj($pObject) & @CRLF)

    Local $vt=0
    SafeArrayGetVartype($pObject, $vt)
    ConsoleWrite("$vt = " & $vt & @CRLF) 
    
    ; SF_UNKNOWN:  The type of the elements contained in the SAFEARRAY MUST be a pointer to IUnknown.
    ; Hex value is 0x0000000D.
    ; Element marshaling size in bytes: 4

EndFunc

Here it stops for me because I have to hand it over to the SafeArray goeroes... ?

Can someone have a look at this to make it work ?

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