Danyfirex Posted April 6, 2017 Share Posted April 6, 2017 ptrex I think It was my fault while traslating the AHK script. You need to conver this to AutoIt Loop % argCount vargs[A_Index-1] := Args[A_Index] basically a SafeArray. If @NumParams >= 3 Then Make a loop and Add the parameter. Something like this for handle the parameters. _Test("X", "X", "P1", "P2", "P3") _Test("X", "X", "Something", 10, 10.10) Func _Test($Pa = "", $Pb = "", $Parameter1 = "", $Parameter2 = "", $Parameter3 = "") If @NumParams >= 3 Then Local $Var=0 For $i = 3 To @NumParams $Var=Eval("Parameter" & ($i-2)) ConsoleWrite($Var & @TAB & "VarType: " & VarGetType($Var) & @CRLF) Next EndIf EndFunc ;==>_Test Saludos Danysys.com AutoIt... UDFs: VirusTotal API 2.0 UDF - libZPlay UDF - Apps: Guitar Tab Tester - VirusTotal Hash Checker Examples: Text-to-Speech ISpVoice Interface - Get installed applications - Enable/Disable Network connection PrintHookProc - WINTRUST - Mute Microphone Level - Get Connected NetWorks - Create NetWork Connection ShortCut Link to comment Share on other sites More sharing options...
trancexx Posted April 6, 2017 Share Posted April 6, 2017 ^^ There's no need for Eval(): Func _Test($Pa = "", $Pb = "", $Parameter1 = "", $Parameter2 = "", $Parameter3 = "") Local $aParams = [$Parameter1, $Parameter2, $Parameter3] If @NumParams >= 3 Then Local $Var = 0 For $i = 0 To @NumParams - 3 $Var = $aParams[$i] ConsoleWrite($Var & @TAB & "VarType: " & VarGetType($Var) & @CRLF) Next EndIf EndFunc ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
ptrex Posted April 6, 2017 Share Posted April 6, 2017 (edited) Dannyfirex / trancexx : thanks for the input ! Something like this NOT TESTED YET ! expandcollapse popupFunc _CRL_CreateObject(ByRef $oAssembly, $sTypeName = "", $sParameter1 = "", $sParameter2 = "", $sParameter3 = "") #forceref $oAssembly, $sTypeName, $sParameter3 If @NumParams = 2 Then Local $oObject = 0 $oAssembly.CreateInstance_2($sTypeName, True, $oObject) Return $oObject EndIf #cs If @NumParams = 3 Then ; static Array_Empty := ComObjArray(0xC,0), null := ComObject(13,0) Local $pSAEmpty, $tSAB = DllStructCreate($tagSAFEARRAYBOUND) DllStructSetData($tSAB, "cElements", 0) DllStructSetData($tSAB, "lLbound", 0) $pSAEmpty = SafeArrayCreate($VT_VARIANT, 0, $tSAB) Local $oObject = 0 $oAssembly.CreateInstance_3($sTypeName, True, 0, 0, CreateSafeArray($sParameter3), 0, $pSAEmpty, $oObject) Return $oObject EndIf #ce If @NumParams >= 3 Then Local $Var = 0 Local $aParams[@NumParams] For $i = 0 To @NumParams - 3 $Var = $aParams[$i] ConsoleWrite($Var & @TAB & "VarType: " & VarGetType($Var) & @CRLF) Next ; static Array_Empty := ComObjArray(0xC,0), null := ComObject(13,0) Local $pSAEmpty, $tSAB = DllStructCreate($tagSAFEARRAYBOUND) DllStructSetData($tSAB, "cElements", 0) DllStructSetData($tSAB, "lLbound", 0) $pSAEmpty = SafeArrayCreate($VT_VARIANT, 0, $tSAB) Local $oObject = 0 $oAssembly.CreateInstance_3($sTypeName, True, 0, 0, CreateSafeArray($aParams), 0, $pSAEmpty, $oObject) Return $oObject EndIf EndFunc ;==>_CRL_CreateObject Edited April 6, 2017 by ptrex Contributions :Firewall Log Analyzer for XP - Creating COM objects without a need of DLL's - UPnP support in AU3Crystal Reports Viewer - PDFCreator in AutoIT - Duplicate File FinderSQLite3 Database functionality - USB Monitoring - Reading Excel using SQLRun Au3 as a Windows Service - File Monitor - Embedded Flash PlayerDynamic Functions - Control Panel Applets - Digital Signing Code - Excel Grid In AutoIT - Constants for Special Folders in WindowsRead data from Any Windows Edit Control - SOAP and Web Services in AutoIT - Barcode Printing Using PS - AU3 on LightTD WebserverMS LogParser SQL Engine in AutoIT - ImageMagick Image Processing - Converter @ Dec - Hex - Bin -Email Address Encoder - MSI Editor - SNMP - MIB ProtocolFinancial Functions UDF - Set ACL Permissions - Syntax HighLighter for AU3ADOR.RecordSet approach - Real OCR - HTTP Disk - PDF Reader Personal Worldclock - MS Indexing Engine - Printing ControlsGuiListView - Navigation (break the 4000 Limit barrier) - Registration Free COM DLL Distribution - Update - WinRM SMART Analysis - COM Object Browser - Excel PivotTable Object - VLC Media Player - Windows LogOnOff Gui -Extract Data from Outlook to Word & Excel - Analyze Event ID 4226 - DotNet Compiler Wrapper - Powershell_COM - New Link to comment Share on other sites More sharing options...
junkew Posted April 7, 2017 Share Posted April 7, 2017 Some things to try based on http://codoid.com/capturing-screen-region/ This below is not working (also not when i remove $x and $y) The System.Drawing.Graphics seems also not creating an object Func _Example() Local $oAssembly = _CLR_LoadLibrary("mscorlib") ConsoleWrite("!$oAssembly: " & IsObj($oAssembly) & @CRLF) Local $oAssDrawing = _CLR_LoadLibrary("System.Drawing") ConsoleWrite("!$oAssDrawing: " & IsObj($oAssDrawing) & @CRLF) local $oGraphic=_CRL_CreateObject($oAssDrawing,"System.Drawing.Graphics") ConsoleWrite("!$oGraphic " & IsObj($oGraphic) & @CRLF) ;~ 'Point structure to specify x and y to capture a region local $x=10 local $y=10 local $oPoint=_CRL_CreateObject($oAssDrawing,"System.Drawing.Point",$X,$Y) $oPoint.x=15 ConsoleWrite("!$oPoint " & IsObj($oPoint) & @CRLF) ConsoleWrite("!$oPoint " & $oPoint.x & @CRLF) EndFunc FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets Link to comment Share on other sites More sharing options...
ptrex Posted April 8, 2017 Share Posted April 8, 2017 (edited) It's not running in VBA we are pretty sure it is a CLR limitation, correct ? The issue is that we probably trying call managed code. As you can read here there are some extra functions needed to do the "unwrap" http://stackoverflow.com/questions/37074533/how-to-call-net-methods-from-excel-vba https://msdn.microsoft.com/nl-nl/library/system.runtime.remoting.objecthandle.unwrap(v=vs.110).aspx More interesting reading here The Complete Interoperability Guide Some User Case Example here : http://netcode.ru/dotnet/?artID=7476 Edited April 8, 2017 by ptrex Contributions :Firewall Log Analyzer for XP - Creating COM objects without a need of DLL's - UPnP support in AU3Crystal Reports Viewer - PDFCreator in AutoIT - Duplicate File FinderSQLite3 Database functionality - USB Monitoring - Reading Excel using SQLRun Au3 as a Windows Service - File Monitor - Embedded Flash PlayerDynamic Functions - Control Panel Applets - Digital Signing Code - Excel Grid In AutoIT - Constants for Special Folders in WindowsRead data from Any Windows Edit Control - SOAP and Web Services in AutoIT - Barcode Printing Using PS - AU3 on LightTD WebserverMS LogParser SQL Engine in AutoIT - ImageMagick Image Processing - Converter @ Dec - Hex - Bin -Email Address Encoder - MSI Editor - SNMP - MIB ProtocolFinancial Functions UDF - Set ACL Permissions - Syntax HighLighter for AU3ADOR.RecordSet approach - Real OCR - HTTP Disk - PDF Reader Personal Worldclock - MS Indexing Engine - Printing ControlsGuiListView - Navigation (break the 4000 Limit barrier) - Registration Free COM DLL Distribution - Update - WinRM SMART Analysis - COM Object Browser - Excel PivotTable Object - VLC Media Player - Windows LogOnOff Gui -Extract Data from Outlook to Word & Excel - Analyze Event ID 4226 - DotNet Compiler Wrapper - Powershell_COM - New Link to comment Share on other sites More sharing options...
junkew Posted April 9, 2017 Share Posted April 9, 2017 VBA has its own limitations. Hosting .NET in VBA is probably not the first thing microsoft would have thought of. VBA Office 2010 I am on and it has limitations in number of types in Variant structure. Not sure if that is better in VBA office 2013. From my side it looks I am more the limitation myself than VBA or AutoIt is. .NET is huge in possibilities but Microsoft seems to be preferring managed implementations. local $oPoint=_CRL_CreateObject($oAssDrawing,"System.Drawing.Point",$X,$Y) creates a value type which is not an object. As far as I understand this know you have to make a small wrapper in managed code with the different reflection solutions to expose back to the unmanaged language. There are multiple examples on codeproject I am trying to understand a little better. Somehow that sounds silly to me as what is then the purpose of hosting from an unmanaged language (like AutoIt) Like larsJ already summarized I feel we should wrap up some stuff and make some nice examples and post the results in examples section to gain some attention from other AutoIt users refer them to this thread so we can more help. Examples for "all" system.collections.* as thats probably most people are interested in Examples for the forms as was done so far (is there any form you cannot do out of the box in AutoIT) .... FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets Link to comment Share on other sites More sharing options...
ptrex Posted April 9, 2017 Share Posted April 9, 2017 (edited) Sure, agree on this... If this is published in the wide open forum. There might be other smart people that can shed some light on this too. But I would suggest first to try some more examples here. Other then GUI examples. I will try to test some too... Edited April 9, 2017 by ptrex Contributions :Firewall Log Analyzer for XP - Creating COM objects without a need of DLL's - UPnP support in AU3Crystal Reports Viewer - PDFCreator in AutoIT - Duplicate File FinderSQLite3 Database functionality - USB Monitoring - Reading Excel using SQLRun Au3 as a Windows Service - File Monitor - Embedded Flash PlayerDynamic Functions - Control Panel Applets - Digital Signing Code - Excel Grid In AutoIT - Constants for Special Folders in WindowsRead data from Any Windows Edit Control - SOAP and Web Services in AutoIT - Barcode Printing Using PS - AU3 on LightTD WebserverMS LogParser SQL Engine in AutoIT - ImageMagick Image Processing - Converter @ Dec - Hex - Bin -Email Address Encoder - MSI Editor - SNMP - MIB ProtocolFinancial Functions UDF - Set ACL Permissions - Syntax HighLighter for AU3ADOR.RecordSet approach - Real OCR - HTTP Disk - PDF Reader Personal Worldclock - MS Indexing Engine - Printing ControlsGuiListView - Navigation (break the 4000 Limit barrier) - Registration Free COM DLL Distribution - Update - WinRM SMART Analysis - COM Object Browser - Excel PivotTable Object - VLC Media Player - Windows LogOnOff Gui -Extract Data from Outlook to Word & Excel - Analyze Event ID 4226 - DotNet Compiler Wrapper - Powershell_COM - New Link to comment Share on other sites More sharing options...
ptrex Posted April 9, 2017 Share Posted April 9, 2017 (edited) I also found this : Remarks This is a convenience method that combines CreateInstance and ObjectHandle.Unwrap. This method calls the default constructor for typeName. https://msdn.microsoft.com/en-us/library/3c4f1xde(v=vs.110).aspx Just to keep us all awake when getting bored Edited April 9, 2017 by ptrex Contributions :Firewall Log Analyzer for XP - Creating COM objects without a need of DLL's - UPnP support in AU3Crystal Reports Viewer - PDFCreator in AutoIT - Duplicate File FinderSQLite3 Database functionality - USB Monitoring - Reading Excel using SQLRun Au3 as a Windows Service - File Monitor - Embedded Flash PlayerDynamic Functions - Control Panel Applets - Digital Signing Code - Excel Grid In AutoIT - Constants for Special Folders in WindowsRead data from Any Windows Edit Control - SOAP and Web Services in AutoIT - Barcode Printing Using PS - AU3 on LightTD WebserverMS LogParser SQL Engine in AutoIT - ImageMagick Image Processing - Converter @ Dec - Hex - Bin -Email Address Encoder - MSI Editor - SNMP - MIB ProtocolFinancial Functions UDF - Set ACL Permissions - Syntax HighLighter for AU3ADOR.RecordSet approach - Real OCR - HTTP Disk - PDF Reader Personal Worldclock - MS Indexing Engine - Printing ControlsGuiListView - Navigation (break the 4000 Limit barrier) - Registration Free COM DLL Distribution - Update - WinRM SMART Analysis - COM Object Browser - Excel PivotTable Object - VLC Media Player - Windows LogOnOff Gui -Extract Data from Outlook to Word & Excel - Analyze Event ID 4226 - DotNet Compiler Wrapper - Powershell_COM - New Link to comment Share on other sites More sharing options...
LarsJ Posted April 9, 2017 Share Posted April 9, 2017 If you replace _CRL_CreateObject and CreateSafeArray in CLR.au3 with the code below it should be possible to handle more parameters. _CRL_CreateObject: Func _CRL_CreateObject(ByRef $oAssembly, $sTypeName, $v3 = Default, $v4 = Default, $v5 = Default, $v6 = Default, $v7 = Default, $v8 = Default, $v9 = Default) Local $aParams = [ $v3, $v4, $v5, $v6, $v7, $v8, $v9 ], $oObject = 0 If @NumParams = 2 Then $oAssembly.CreateInstance_2($sTypeName, True, $oObject) Return $oObject EndIf Local $iArgs = @NumParams - 2, $aArgs[$iArgs] For $i = 0 To $iArgs - 1 $aArgs[$i] = $aParams[$i] Next ; static Array_Empty := ComObjArray(0xC,0), null := ComObject(13,0) Local $pSAEmpty, $tSAB = DllStructCreate($tagSAFEARRAYBOUND) DllStructSetData($tSAB, "cElements", 0) DllStructSetData($tSAB, "lLbound", 0) $pSAEmpty = SafeArrayCreate($VT_VARIANT, 0, $tSAB) $oAssembly.CreateInstance_3($sTypeName, True, 0, 0, CreateSafeArray($aArgs), 0, $pSAEmpty, $oObject) Return $oObject EndFunc ;==>_CRL_CreateObject CreateSafeArray: Func CreateSafeArray( $aArgs ) Local $tSafeArrayBound = DllStructCreate($tagSAFEARRAYBOUND) Local $iArgs = UBound( $aArgs ), $pSafeArray, $pSafeArrayData DllStructSetData($tSafeArrayBound, "cElements", $iArgs) $pSafeArray = SafeArrayCreate($VT_VARIANT, 1, $tSafeArrayBound) SafeArrayAccessData($pSafeArray, $pSafeArrayData) For $i = 0 To $iArgs - 1 Switch VarGetType( $aArgs[$i] ) Case "Bool" DllStructSetData(DllStructCreate("word", $pSafeArrayData), 1, $VT_BOOL) DllStructSetData(DllStructCreate("short", $pSafeArrayData + 8), 1, $aArgs[$i]) Case "Double" DllStructSetData(DllStructCreate("word", $pSafeArrayData), 1, $VT_R8) DllStructSetData(DllStructCreate("double", $pSafeArrayData + 8), 1, $aArgs[$i]) Case "Int32" DllStructSetData(DllStructCreate("word", $pSafeArrayData), 1, $VT_I4) DllStructSetData(DllStructCreate("int", $pSafeArrayData + 8), 1, $aArgs[$i]) Case "String" DllStructSetData(DllStructCreate("word", $pSafeArrayData), 1, $VT_BSTR) DllStructSetData(DllStructCreate("ptr", $pSafeArrayData + 8), 1, SysAllocString($aArgs[$i])) EndSwitch $pSafeArrayData += @AutoItX64 ? 24 : 16 Next SafeArrayUnaccessData($pSafeArray) Return $pSafeArray EndFunc ;==>CreateSafeArray Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions Link to comment Share on other sites More sharing options...
junkew Posted April 9, 2017 Share Posted April 9, 2017 (edited) Extensions from LarsJ are exactly the points I am having trouble with on how to map as there seems not to be one table in AutoIt telling me all the types we somehow support Help file datatypes gives me Data Sub-type Range and Notes Int32 A 32bit signed integer number. Int64 A 64bit signed integer number Double A double-precision floating point number. String Can contain strings of up to 2147483647 characters. Binary Binary data, can contain up to 2147483647 bytes. Pointer A memory address pointer. 32bit or 64bit depending on the version of AutoIt used. Help file DllStructCreate gives me some more together with objCreate and objCreateInterface .NET gives me https://msdn.microsoft.com/en-us/library/ya5y69ds.aspx VARIANT struct gives me (or in detail in windows SDK include files) https://msdn.microsoft.com/en-us/library/windows/desktop/ms221627(v=vs.85).aspx And if I then try to use some system.windows.point to put a position of a button its somehow not working I can understand why as its most likely a structure and not an object (same for system.drawing.point) local $oPoint=_CRL_CreateObject($oAssembly,"System.Windows.Point",150,50) ConsoleWrite("!$oPoint " & IsObj($oPoint) & @CRLF) ConsoleWrite("!$oPoint " & $oPoint.x & @CRLF) When you have the point it should be possible to do btn.location=$oPoint left/top properties work fine but its more for my understanding on how to map differences between struct/enum and object/properties. All examples I found so far on the internet make a small wrapper around dynamicobject with the try... methods available since .NET 4.0 in a C# object which you can reach from unmanaged code by com. Edited April 9, 2017 by junkew FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets Link to comment Share on other sites More sharing options...
ptrex Posted April 10, 2017 Share Posted April 10, 2017 A few more Examples to include in the release : expandcollapse popup;#AutoIt3Wrapper_UseX64=y #include "CLR.Au3" _Example() Func _Example() Local $oAssembly = _CLR_LoadLibrary("mscorlib") ConsoleWrite("!$oAssembly: " & IsObj($oAssembly) & @CRLF) ;1. System.Random Example ; https://msdn.microsoft.com/en-us/library/system.random(v=vs.110).aspx local $oRnd =_CRL_CreateObject($oAssembly,"System.Random") ConsoleWrite("!$oRnd " & IsObj($oRnd) & @CRLF) MsgBox(0,".Net CLR", "System.Random # : " & $oRnd.next() & @CRLF) ;2. System.String Example ; https://msdn.microsoft.com/en-us/library/system.string(v=vs.110).aspx local $oText =_CRL_CreateObject($oAssembly,"System.Text.UTF8Encoding") ConsoleWrite("!$oText " & IsObj($oText) & @CRLF & @CRLF) local $sPswd = "P@ssW0rd" MsgBox(0,".Net CLR",$sPswd & " Text Using : " & @CRLF & "System.Text.UTF8Encoding :" & @CRLF & @CRLF & $oText.GetBytes_4($sPswd)) local $oSHA512 =_CRL_CreateObject($oAssembly,"System.Security.Cryptography.SHA512Managed") ConsoleWrite($oSHA512.ComputeHash_2($oText.GetBytes_4("P@ssW0rd")) & @CRLF) MsgBox(0,".Net CLR",$sPswd & " UTF8Encoding To : " & @CRLF & "System.Security.Cryptography.SHA512Managed :" & @CRLF & @CRLF & $oSHA512.ComputeHash_2($oText.GetBytes_4("P@ssW0rd"))) ;3. SafeArray RankMismatch Example ; https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.safearrayrankmismatchexception(v=vs.110).aspx local $oSafeArrayError =_CRL_CreateObject($oAssembly,"System.Runtime.InteropServices.SafeArrayRankMismatchException") ConsoleWrite(@CRLF & "$oSafeArrayError Obj. : " & IsObj($oSafeArrayError) & @CRLF & _ "SafeArrayRankMismatch intercepted !" & @CRLF & _ $oSafeArrayError.data & @CRLF & _ $oSafeArrayError.HelpLink & @CRLF & _ $oSafeArrayError.HResult & @CRLF & _ $oSafeArrayError.InnerException & @CRLF & _ $oSafeArrayError.Message & @CRLF & _ $oSafeArrayError.Source & @CRLF & _ $oSafeArrayError.StackTrace & @CRLF & _ $oSafeArrayError.TargetSite) Endfunc Hi Larj, As Junkew mentioned already the multi-parameter version you posted did not solve the issue unfortunately. The only possibility is we can get this approach running : https://msdn.microsoft.com/en-us/library/3c4f1xde(v=vs.110).aspx What started off as a mission impossible ended up in a nice project. Which has much more potential then we have seen so far... mLipok 1 Contributions :Firewall Log Analyzer for XP - Creating COM objects without a need of DLL's - UPnP support in AU3Crystal Reports Viewer - PDFCreator in AutoIT - Duplicate File FinderSQLite3 Database functionality - USB Monitoring - Reading Excel using SQLRun Au3 as a Windows Service - File Monitor - Embedded Flash PlayerDynamic Functions - Control Panel Applets - Digital Signing Code - Excel Grid In AutoIT - Constants for Special Folders in WindowsRead data from Any Windows Edit Control - SOAP and Web Services in AutoIT - Barcode Printing Using PS - AU3 on LightTD WebserverMS LogParser SQL Engine in AutoIT - ImageMagick Image Processing - Converter @ Dec - Hex - Bin -Email Address Encoder - MSI Editor - SNMP - MIB ProtocolFinancial Functions UDF - Set ACL Permissions - Syntax HighLighter for AU3ADOR.RecordSet approach - Real OCR - HTTP Disk - PDF Reader Personal Worldclock - MS Indexing Engine - Printing ControlsGuiListView - Navigation (break the 4000 Limit barrier) - Registration Free COM DLL Distribution - Update - WinRM SMART Analysis - COM Object Browser - Excel PivotTable Object - VLC Media Player - Windows LogOnOff Gui -Extract Data from Outlook to Word & Excel - Analyze Event ID 4226 - DotNet Compiler Wrapper - Powershell_COM - New Link to comment Share on other sites More sharing options...
junkew Posted April 10, 2017 Share Posted April 10, 2017 (edited) array<Object^>^ args, Do we think above states its a safearray? Local $oAssembly = _CLR_LoadLibrary("mscorlib") ConsoleWrite("!$oAssembly: " & IsObj($oAssembly) & @CRLF) Local $oArrayList = _CRL_CreateObject($oAssembly, "System.Collections.ArrayList") maybe we can pass $oArrList to _CLR_CreateObject internal createinstance. ;~Local $iArgs = @NumParams - 2, $aArgs[$iArgs] Local $oAssembly = _CLR_LoadLibrary("mscorlib") ConsoleWrite("!$oAssembly: " & IsObj($oAssembly) & @CRLF) $oArrayList=$oAssembly.CreateInstance_2("System.Collections.ArrayList", True, 0) ConsoleWrite("!$oArrayList: " & IsObj($oArrayList) & @CRLF) For $i = 0 To $iArgs - 1 $oArrayList.Add($aParams[$i]) Next $oAssembly.CreateInstance_3($sTypeName, True, 0, 0, $oArrayList, 0, $pSAEmpty, $oObject) Will try to clean up to see if above works. Didn't work see more plain code: https://searchcode.com/codesearch/view/59947170/ which indicates logic on safearray is right https://docs.microsoft.com/en-us/dotnet/articles/framework/interop/default-marshaling-for-arrays Edited April 11, 2017 by junkew reference to marshaling of arrays FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets Link to comment Share on other sites More sharing options...
ptrex Posted April 11, 2017 Share Posted April 11, 2017 This is again a lot of SafeArray material you posted in those links... good to read but not my cup of tea to honest... The link you posted from "Searchcode.com" has everything covered apparently Just for information, you can create a .Net Array like this as well, because it is COM Visible $oArray = ObjCreate( "System.Collections.ArrayList") $oArray.Add("F") $oArray.Add("D") $oArray.Add("B") $oArray.Add("C") $oArray.Sort For $i in $oArray ConsoleWrite($i & @CRLF) Next Contributions :Firewall Log Analyzer for XP - Creating COM objects without a need of DLL's - UPnP support in AU3Crystal Reports Viewer - PDFCreator in AutoIT - Duplicate File FinderSQLite3 Database functionality - USB Monitoring - Reading Excel using SQLRun Au3 as a Windows Service - File Monitor - Embedded Flash PlayerDynamic Functions - Control Panel Applets - Digital Signing Code - Excel Grid In AutoIT - Constants for Special Folders in WindowsRead data from Any Windows Edit Control - SOAP and Web Services in AutoIT - Barcode Printing Using PS - AU3 on LightTD WebserverMS LogParser SQL Engine in AutoIT - ImageMagick Image Processing - Converter @ Dec - Hex - Bin -Email Address Encoder - MSI Editor - SNMP - MIB ProtocolFinancial Functions UDF - Set ACL Permissions - Syntax HighLighter for AU3ADOR.RecordSet approach - Real OCR - HTTP Disk - PDF Reader Personal Worldclock - MS Indexing Engine - Printing ControlsGuiListView - Navigation (break the 4000 Limit barrier) - Registration Free COM DLL Distribution - Update - WinRM SMART Analysis - COM Object Browser - Excel PivotTable Object - VLC Media Player - Windows LogOnOff Gui -Extract Data from Outlook to Word & Excel - Analyze Event ID 4226 - DotNet Compiler Wrapper - Powershell_COM - New Link to comment Share on other sites More sharing options...
ptrex Posted April 12, 2017 Share Posted April 12, 2017 More readings brings us to this restriction https://msdn.microsoft.com/en-us/library/8skskf63.aspx Quote Applications that receive less than full trust from their host or sandbox are not allowed to call shared managed libraries unless the library writer specifically allows them to through the use of the AllowPartiallyTrustedCallersAttribute attribute. Therefore, application writers must be aware that some libraries will not be available to them from a partially trusted context. ... Libraries must be signed with a strong name in order to be shared by multiple applications. Strong names allow your code to be placed in the global assembly cache or added to the full-trust list of a sandboxing AppDomain, and allow consumers to verify that a particular piece of mobile code actually originates from you. ... In order to disable the automatic LinkDemand and prevent the exception from being thrown, you can place the AllowPartiallyTrustedCallersAttribute attribute on the assembly scope of a shared library. This attribute allows your libraries to be called from partially trusted managed code. Partially trusted code that is granted access to a library with this attribute is still subject to further restrictions defined by the AppDomain. There is no programmatic way for partially trusted code to call a library that does not have the AllowPartiallyTrustedCallersAttribute attribute. This might be why we are not able to call the method of the .Net assemblies ... Contributions :Firewall Log Analyzer for XP - Creating COM objects without a need of DLL's - UPnP support in AU3Crystal Reports Viewer - PDFCreator in AutoIT - Duplicate File FinderSQLite3 Database functionality - USB Monitoring - Reading Excel using SQLRun Au3 as a Windows Service - File Monitor - Embedded Flash PlayerDynamic Functions - Control Panel Applets - Digital Signing Code - Excel Grid In AutoIT - Constants for Special Folders in WindowsRead data from Any Windows Edit Control - SOAP and Web Services in AutoIT - Barcode Printing Using PS - AU3 on LightTD WebserverMS LogParser SQL Engine in AutoIT - ImageMagick Image Processing - Converter @ Dec - Hex - Bin -Email Address Encoder - MSI Editor - SNMP - MIB ProtocolFinancial Functions UDF - Set ACL Permissions - Syntax HighLighter for AU3ADOR.RecordSet approach - Real OCR - HTTP Disk - PDF Reader Personal Worldclock - MS Indexing Engine - Printing ControlsGuiListView - Navigation (break the 4000 Limit barrier) - Registration Free COM DLL Distribution - Update - WinRM SMART Analysis - COM Object Browser - Excel PivotTable Object - VLC Media Player - Windows LogOnOff Gui -Extract Data from Outlook to Word & Excel - Analyze Event ID 4226 - DotNet Compiler Wrapper - Powershell_COM - New Link to comment Share on other sites More sharing options...
ptrex Posted April 13, 2017 Share Posted April 13, 2017 (edited) Hi all, Hope you all have not abandoned the project yet Giving a long weekend ahead of us and bad weather, give us all lot's of free time. Lets recapitulate where we are : Most of the things are working, EXCEPT we are not able yet to get access to the native .NET Classes - Methods / Properties / Events etc, Using the _CRL_CreateObject(), not even with the multi parameter version that was created by Larsj ... Information so far : Apart from the security issues that might be in the middle see post 121. Which I am not convinced that this is the mean reason why it is not working. I found this article showing a working version in VBA : Start reading as of Quote .... Here's your solution, tested for .NET 2.0 and .NET 4.0, 32 bit and 64 bit, courtesy of Soraco Technologies. http://stackoverflow.com/questions/37074533/how-to-call-net-methods-from-excel-vba See this example code : Quote Private Declare PtrSafe Function CorBindToRuntimeEx Lib "mscoree" ( _ ByVal pwszVersion As LongPtr, _ ByVal pwszBuildFlavor As LongPtr, _ ByVal startupFlags As Long, _ ByRef rclsid As Long, _ ByRef riid As Long, _ ByRef ppvObject As mscoree.CorRuntimeHost) As Long Private Declare PtrSafe Function VariantCopy Lib "oleaut32" (dest, src) As Long '' ' Creates a .Net object with the CLR 4 without registration. ' '' Function CreateInstance(assembly As String, typeName As String) As Variant Const CLR$ = "v4.0.30319" Static domain As mscorlib.AppDomain If domain Is Nothing Then Dim host As mscoree.CorRuntimeHost, hr&, T&(0 To 7) T(0) = &HCB2F6723: T(1) = &H11D2AB3A: T(2) = &HC000409C: T(3) = &H3E0AA34F T(4) = &HCB2F6722: T(5) = &H11D2AB3A: T(6) = &HC000409C: T(7) = &H3E0AA34F hr = CorBindToRuntimeEx(StrPtr(CLR), 0, 3, T(0), T(4), host) If hr And -2 Then err.Raise hr host.Start host.GetDefaultDomain domain End If VariantCopy CreateInstance, domain.CreateInstanceFrom(assembly, typeName).Unwrap End Function If you look at this you can definitely access native .Net Classes. in an unmanaged Host. Keep in mind that in this code they CorBindToRuntimeEX function, which is obsolete on the meantime. And replaced by the CreateInstance function is CLR. Review : A. This code made me go back to the drawing board and think why does it not work when we instantiate the Object. And AFTERWARD try to access the methods ? B. So we need to take 1 step back and have a look in which functions are available in the CLR APDDOMAIN function has to offer ? And what we see is that in the MSCORLIB -> Appdomain there it is where it is ALL HAPPENING : Global Const $sIID_IAppDomain = "{05F696DC-2B29-3663-AD8B-C4389CF2A713}" Global Const $sTag_IAppDomain = _ ... "remove_AssemblyResolve hresult();" & _ "add_UnhandledException hresult();" & _ "remove_UnhandledException hresult();" & _ "DefineDynamicAssembly hresult();" & _ "DefineDynamicAssembly_2 hresult();" & _ "DefineDynamicAssembly_3 hresult();" & _ "DefineDynamicAssembly_4 hresult();" & _ "DefineDynamicAssembly_5 hresult();" & _ "DefineDynamicAssembly_6 hresult();" & _ "DefineDynamicAssembly_7 hresult();" & _ "DefineDynamicAssembly_8 hresult();" & _ "DefineDynamicAssembly_9 hresult();" & _ "CreateInstance hresult(bstr;bstr;object*);" & _ "CreateInstanceFrom hresult();" & _ "CreateInstance_2 hresult();" & _ "CreateInstanceFrom_2 hresult();" & _ "CreateInstance_3 hresult();" & _ "CreateInstanceFrom_3 hresult();" & _ "Load hresult();" & _ "Load_2 hresult();" & _ "Load_3 hresult();" & _ ... Meaning that the we need to access the methods as is demontrated in the VBA example. Quote domain.CreateInstanceFrom(assembly, typeName).Unwrap Starting off from the Appdomain using the unique Assembly referance like for example ; mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 and not after the the creation of the CRL_CREATEOBJECT ? If you take a look using ILSpy in the MSCORLIB you will see that the majority .NET framework is relying on this single Assembly/ We are not far of from getting it done ... believe me MSCORLIB is where the gold is ... I will try to post some trial and errors later today, to see how far I get ... I hope you guys are not giving up this close to the finish line ? Edited April 13, 2017 by ptrex Gianni 1 Contributions :Firewall Log Analyzer for XP - Creating COM objects without a need of DLL's - UPnP support in AU3Crystal Reports Viewer - PDFCreator in AutoIT - Duplicate File FinderSQLite3 Database functionality - USB Monitoring - Reading Excel using SQLRun Au3 as a Windows Service - File Monitor - Embedded Flash PlayerDynamic Functions - Control Panel Applets - Digital Signing Code - Excel Grid In AutoIT - Constants for Special Folders in WindowsRead data from Any Windows Edit Control - SOAP and Web Services in AutoIT - Barcode Printing Using PS - AU3 on LightTD WebserverMS LogParser SQL Engine in AutoIT - ImageMagick Image Processing - Converter @ Dec - Hex - Bin -Email Address Encoder - MSI Editor - SNMP - MIB ProtocolFinancial Functions UDF - Set ACL Permissions - Syntax HighLighter for AU3ADOR.RecordSet approach - Real OCR - HTTP Disk - PDF Reader Personal Worldclock - MS Indexing Engine - Printing ControlsGuiListView - Navigation (break the 4000 Limit barrier) - Registration Free COM DLL Distribution - Update - WinRM SMART Analysis - COM Object Browser - Excel PivotTable Object - VLC Media Player - Windows LogOnOff Gui -Extract Data from Outlook to Word & Excel - Analyze Event ID 4226 - DotNet Compiler Wrapper - Powershell_COM - New Link to comment Share on other sites More sharing options...
junkew Posted April 13, 2017 Share Posted April 13, 2017 I am certainly not giving up but I think the solution is in safearray (and in the other parts a lot of reading and trying) https://msdn.microsoft.com/en-us/library/windows/desktop/ms221558(v=vs.85).aspx as far as I can see the safearray.au3 is a multidimensional array and not a one-dimensional array. So when we extend safearray.au3 with the SafeArrayCreateVector function it most likely will work. DotnetFacorty is doing a small .NET wrapper class around with a createinstance(....,...., par1,par2,par3, .....) and then first make the par1,par n into an array before it calls the actual createinstance method. All comvisible=false you most likely only reach thru a .NET wrapper class that makes use of the reflection or dynamic parts of later .net versions interesting link you share for VBA. this way VBA will never die ;-) FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets Link to comment Share on other sites More sharing options...
ptrex Posted April 13, 2017 Share Posted April 13, 2017 If I read this code it show what we see in the VBA code ; https://msdn.microsoft.com/en-us/library/bs22fky4(v=vs.110).aspx domain.CreateInstance("Assembly text name, Version, Culture, PublicKeyToken", "MyDynamicType"); expandcollapse popupusing System; using System.Reflection; using System.Reflection.Emit; class Test { public static void Main() { AppDomain currentDomain = AppDomain.CurrentDomain; InstantiateMyDynamicType(currentDomain); // Failed! currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler); InstantiateMyDynamicType(currentDomain); // OK! } static void InstantiateMyDynamicType(AppDomain domain) { try { // You must supply a valid fully qualified assembly name here. domain.CreateInstance("Assembly text name, Version, Culture, PublicKeyToken", "MyDynamicType"); } catch (Exception e) { Console.WriteLine(e.Message); } } static Assembly MyResolveEventHandler(object sender, ResolveEventArgs args) { return DefineDynamicAssembly((AppDomain) sender); } static Assembly DefineDynamicAssembly(AppDomain domain) { // Build a dynamic assembly using Reflection Emit API. AssemblyName assemblyName = new AssemblyName(); assemblyName.Name = "MyDynamicAssembly"; AssemblyBuilder assemblyBuilder = domain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MyDynamicModule"); TypeBuilder typeBuilder = moduleBuilder.DefineType("MyDynamicType", TypeAttributes.Public); ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, null); ILGenerator ilGenerator = constructorBuilder.GetILGenerator(); ilGenerator.EmitWriteLine("MyDynamicType instantiated!"); ilGenerator.Emit(OpCodes.Ret); typeBuilder.CreateType(); return assemblyBuilder; } } If you can figger out the SafeArray mistery, then I will do some Appdomain trial and errors Here we see all the AppDomain COM interfaces : https://msdn.microsoft.com/en-us/library/system._appdomain(v=vs.110).aspx Global Const $sIID_IAppDomain = "{05F696DC-2B29-3663-AD8B-C4389CF2A713}" Global Const $sTag_IAppDomain = _ "GetTypeInfoCount hresult();" & _ "GetTypeInfo hresult();" & _ "GetIDsOfNames hresult();" & _ "Invoke hresult();" & _ "get_ToString hresult();" & _ "Equals hresult();" & _ "GetHashCode hresult();" & _ "GetType hresult(ptr*);" & _ "InitializeLifetimeService hresult();" & _ "GetLifetimeService hresult();" & _ "get_Evidence hresult();" & _ "add_DomainUnload hresult();" & _ "remove_DomainUnload hresult();" & _ "add_AssemblyLoad hresult();" & _ "remove_AssemblyLoad hresult();" & _ "add_ProcessExit hresult();" & _ "remove_ProcessExit hresult();" & _ "add_TypeResolve hresult();" & _ "remove_TypeResolve hresult();" & _ "add_ResourceResolve hresult();" & _ "remove_ResourceResolve hresult();" & _ "add_AssemblyResolve hresult();" & _ ... So this should be something that would return an object ? $oDomain1.CreateInstance("mscorlib","Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089","System.Text") Contributions :Firewall Log Analyzer for XP - Creating COM objects without a need of DLL's - UPnP support in AU3Crystal Reports Viewer - PDFCreator in AutoIT - Duplicate File FinderSQLite3 Database functionality - USB Monitoring - Reading Excel using SQLRun Au3 as a Windows Service - File Monitor - Embedded Flash PlayerDynamic Functions - Control Panel Applets - Digital Signing Code - Excel Grid In AutoIT - Constants for Special Folders in WindowsRead data from Any Windows Edit Control - SOAP and Web Services in AutoIT - Barcode Printing Using PS - AU3 on LightTD WebserverMS LogParser SQL Engine in AutoIT - ImageMagick Image Processing - Converter @ Dec - Hex - Bin -Email Address Encoder - MSI Editor - SNMP - MIB ProtocolFinancial Functions UDF - Set ACL Permissions - Syntax HighLighter for AU3ADOR.RecordSet approach - Real OCR - HTTP Disk - PDF Reader Personal Worldclock - MS Indexing Engine - Printing ControlsGuiListView - Navigation (break the 4000 Limit barrier) - Registration Free COM DLL Distribution - Update - WinRM SMART Analysis - COM Object Browser - Excel PivotTable Object - VLC Media Player - Windows LogOnOff Gui -Extract Data from Outlook to Word & Excel - Analyze Event ID 4226 - DotNet Compiler Wrapper - Powershell_COM - New Link to comment Share on other sites More sharing options...
ptrex Posted April 14, 2017 Share Posted April 14, 2017 Some more background info regarding Appdomain.CreateInstance() http://www.codemag.com/Article/021108 Quote Creating Code in Alternate AppDomains Loading an assembly and creating a class instance from it in a different application domain involves the following steps: · Create a new AppDomain. · Dynamically create the dynamic assembly and store it to disk. · Create a separate assembly that acts as an object factory and returns an Interface rather than a physical object reference. This assembly can be generic and is reusable but must be a separate DLL from the rest of the application. · Create an object reference using AppDomain::CreateInstance and then call a method to return the remote Interface. Note the important point here is that an Interface not an object reference is returned. · Use the Interface to call into the remote object indirectly using a custom method that performs the passthrough calls to the remote object. The whole point of this convoluted exercise is to load the object into another AppDomain and access it without using any of the object's type information. Accessing type information via Reflection forces an assembly to load into the local AppDomain and this is exactly what we want to avoid. By using a proxy that only publishes an Interface your code load only a single assembly that publishes this generic Interface. Contributions :Firewall Log Analyzer for XP - Creating COM objects without a need of DLL's - UPnP support in AU3Crystal Reports Viewer - PDFCreator in AutoIT - Duplicate File FinderSQLite3 Database functionality - USB Monitoring - Reading Excel using SQLRun Au3 as a Windows Service - File Monitor - Embedded Flash PlayerDynamic Functions - Control Panel Applets - Digital Signing Code - Excel Grid In AutoIT - Constants for Special Folders in WindowsRead data from Any Windows Edit Control - SOAP and Web Services in AutoIT - Barcode Printing Using PS - AU3 on LightTD WebserverMS LogParser SQL Engine in AutoIT - ImageMagick Image Processing - Converter @ Dec - Hex - Bin -Email Address Encoder - MSI Editor - SNMP - MIB ProtocolFinancial Functions UDF - Set ACL Permissions - Syntax HighLighter for AU3ADOR.RecordSet approach - Real OCR - HTTP Disk - PDF Reader Personal Worldclock - MS Indexing Engine - Printing ControlsGuiListView - Navigation (break the 4000 Limit barrier) - Registration Free COM DLL Distribution - Update - WinRM SMART Analysis - COM Object Browser - Excel PivotTable Object - VLC Media Player - Windows LogOnOff Gui -Extract Data from Outlook to Word & Excel - Analyze Event ID 4226 - DotNet Compiler Wrapper - Powershell_COM - New Link to comment Share on other sites More sharing options...
junkew Posted April 15, 2017 Share Posted April 15, 2017 Added 2 variant functions 1st one creates a static array directly fixed number of parameters 2nd one removes the need for SafeArrayAccessData / SafeArrayUnAccessData ;~ SAFEARRAY* SafeArrayCreateVector(_In_ VARTYPE vt, _In_ LONG lLbound, _In_ ULONG cElements); Func SafeArrayCreateVector($vType, $ilBound, $cElements) Local $aCall = DllCall("OleAut32.dll", "ptr", "SafeArrayCreateVector", "dword", $vType, "LONG", $ilBound, 'ULONG', $cElements) If @error Then Return SetError(1, 0, 0) Return $aCall[0] EndFunc ;~ HRESULT SafeArrayPutElement( _In_ SAFEARRAY *psa, _In_ LONG *rgIndices, _In_ void *pv); Func SafeArrayPutElement($pSA, $rgIndices, $pv) Local $aCall = DllCall("OleAut32.dll", "long", "SafeArrayPutElement", "ptr", $pSA, "LONG", $rgIndices, 'ptr', $pv) If @error Then Return SetError(1, 0, 0) Return $aCall[0] EndFunc transforming parts of https://searchcode.com/codesearch/view/59947170/ to see If with a parametrized create_instance3 we get an object to have a clear parametrized example working without direct complexity of point / forms classes that could lead to other issues expandcollapse popup// Strings for CreateInstance_3 asmName = SysAllocString(L"mscorlib"); typeName = SysAllocString(L"System.Collections.ArrayList"); // Create a 1D array with one integer element SAFEARRAY* psa = SafeArrayCreateVector(VT_VARIANT, 0, 1); VariantInit(¶m); param.vt = VT_I4; param.lVal = 128; LONG index = 0; hresult = SafeArrayPutElement(psa, &index, ¶m); if (FAILED(hresult)) { printf("ERROR: Cannot set SAFEARRAY element: 0x%x\n", hresult); Cleanup(); return -1; } // Create an instance of ArrayList using a parameterized constructor hresult = pDomain->CreateInstance_3(asmName, typeName, VARIANT_TRUE, BindingFlags_Default, NULL, psa, NULL, NULL, NULL, &pHandle); if (FAILED(hresult)) { printf("ERROR: Cannot create instance: 0x%x\n", hresult); Cleanup(); return -1; } // Unwrap the ArrayList instance inside the ObjectHandle VariantInit(&arrayList); hresult = pHandle->Unwrap(&arrayList); if (FAILED(hresult)) { printf("ERROR: Could not unwrap object handle: 0x%x\n", hresult); Cleanup(); return -1; } // Get the IDispatch interface so we can call the Capacity property hresult = arrayList.punkVal->QueryInterface(IID_IDispatch, (void**)&pDisp); if (FAILED(hresult)) { printf("ERROR: Could not get IDispatch interface pointer: 0x%x\n", hresult); Cleanup(); return -1; } // Get the DISPID for the Capacity property OLECHAR* name = L"Capacity"; DISPID dispid; hresult = pDisp->GetIDsOfNames(IID_NULL, &name, 1, GetUserDefaultLCID(), &dispid); if (FAILED(hresult)) { printf("ERROR: GetIDsOfNames failed: 0x%x\n", hresult); Cleanup(); return -1; } // Invoke the Capacity property VARIANT result; VariantInit(&result); DISPPARAMS params = { NULL, NULL, 0, 0 }; hresult = pDisp->Invoke(dispid, IID_NULL, GetUserDefaultLCID(), DISPATCH_PROPERTYGET, ¶ms, &result, NULL, NULL); if (FAILED(hresult)) { printf("ERROR: Invoke failed: 0x%x\n", hresult); Cleanup(); return -1; } printf("ArrayList Capacity: %d\n", result.lVal); I assume I need AutoITObject.au3 Is there an alternative to Func _AutoItObject_VariantSet($pVar, $vVal, $iSpecialType = 0) to create a variant? FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets Link to comment Share on other sites More sharing options...
LarsJ Posted April 16, 2017 Share Posted April 16, 2017 (edited) The code can be translated into AutoIt this way: ;#AutoIt3Wrapper_UseX64=y #include "CLR.au3" Example() Func Example() Local $oAppDomain = _CLR_GetDefaultDomain() ; Create a 1D array with one integer element Local $aArgs = [ 128 ], $psa = CreateSafeArray( $aArgs ) ; Create an instance of ArrayList using a parameterized constructor Local $pHandle $oAppDomain.CreateInstance_3( "mscorlib", "System.Collections.ArrayList", True, 0, 0, $psa, 0, 0, 0, $pHandle ) ConsoleWrite( @CRLF & "$pHandle = " & $pHandle & @CRLF ) Local $oHandle = ObjCreateInterface( $pHandle, $sIID_IObjectHandle, $sTag_IObjectHandle ) ConsoleWrite( @CRLF & "IsObj( $oHandle ) = " & IsObj( $oHandle ) & @CRLF ) ; Unwrap the ArrayList instance inside the ObjectHandle Local $oArrayList $oHandle.Unwrap( $oArrayList ) ConsoleWrite( @CRLF & "IsObj( $oArrayList ) = " & IsObj( $oArrayList ) & @CRLF ) ; Print ArrayList Capacity ConsoleWrite( @CRLF & "$oArrayList.Capacity() = " & $oArrayList.Capacity() & @CRLF ) EndFunc CLR.au3.7z Edited April 16, 2017 by LarsJ Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now