Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 12/06/2016 in all areas

  1. Luigi

    MyRiverRaid

    A simple example using IrrLitch to render an airplane moving through a finite map in infinite loop. The map was built with the Tiled Map Editor and the code translates 2d images into its 3D equivalent. Q changes the camera (3 angles) T moves up G down arrows (up, down, left, right) movement https://github.com/chechelaky/MyRiverRaid
    2 points
  2. Version 3.1.0

    647 downloads

    Here is an UDF for managing printers. Features are : - add, remove or rename a printer - add or remove a driver - add or remove a TCP/IP printer port - add or remove a LPR printer port - connect to a remote printer - enum printers and there configuration and properties - pause resume or cancel all jobs of a printer - checks if a printer exists - print a test page - set the default printer
    1 point
  3. Gif

    WMI Tasks

    Hello everyone, This is my first OFFICIAL post on the example scripts forum as i tend to post only things that might help other people or are advanced enough. Well i at least hope that someone might find them useful. It's a list of WMI Tasks concerning several subjects such as Disks, Hardware, Software, Operating System etc. etc. I hope those functions will come useful and someone might like some of them Opt('MustDeclareVars', 1) #region #NoTrayIcon #Include <Array.au3> #endregion ;==================================================================================== ; Programmed by: Tefkros Pavlou (Gif) , www.randomsoft.tk ; Reference at: http://msdn2.microsoft.com ; WINMGMTS functions ;==================================================================================== MsgBox(64, 'Mouse Properties', _Mouse_Properties()) MsgBox(64, 'Processor Speed', _Processor_Speed()) MsgBox(64, 'Computer Type', _Computer_Type()) MsgBox(64, 'Total RAM installed', _Physical_RAM_Available()) MsgBox(64, 'Number of Processors', _Number_Of_Processors()) MsgBox(64, 'Floppy check', _Check_Floppy()) MsgBox(64, 'MS Office Version', _Office_GetVersion()) MsgBox(64, 'Operating System Status', _Determine_Operating_System_Status()) MsgBox(64, 'Detailed Date/Time', _Retrieve_Date_And_Time()) MsgBox(64, 'Time Zone', _Get_Time_Zone()) MsgBox(64, 'Username', _Get_Username()) Global $Accounts_Array = _Get_Local_Accounts() If ($Accounts_Array <> 0) Then _ArrayDisplay($Accounts_Array, 'Local Accounts') Global $Drives_Array = _Drives_Determine() If ($Drives_Array <> 0) Then _ArrayDisplay($Drives_Array, 'Drives (determine DVD drives)') Global $usb_Array = _USB_Devices() If ($usb_Array <> 0) Then _ArrayDisplay($usb_Array, 'USB Devices') Global $Logs_Array = _Get_Events_From_Log() If ($Logs_Array <> 0) Then _ArrayDisplay($Logs_Array, 'Local Accounts') Global $Startup_Services_Array = _Get_Startup_Services() If ($Startup_Services_Array <> 0) Then _ArrayDisplay($Startup_Services_Array, 'Startup Items') Exit (0) Func _Mouse_Properties() Local $a_Text = '' Dim $Obj_WMIService = ObjGet('winmgmts:\\' & @ComputerName & '\root\cimv2'); If (IsObj($Obj_WMIService)) And (Not @error) Then Dim $Col_Items = $Obj_WMIService.ExecQuery('Select * from Win32_PointingDevice') Local $Obj_Item For $Obj_Item In $Col_Items Local $a_Text = 'Description: ' & $Obj_Item.Description & @CRLF $a_Text &= 'Device ID: ' & $Obj_Item.DeviceID & @CRLF $a_Text &= 'Device Interface: ' & $Obj_Item.DeviceInterface & @CRLF $a_Text &= 'Double Speed Threshold: ' & $Obj_Item.DoubleSpeedThreshold & @CRLF $a_Text &= 'Handedness: ' & $Obj_Item.Handedness & @CRLF $a_Text &= 'Hardware Type: ' & $Obj_Item.HardwareType & @CRLF $a_Text &= 'INF File Name: ' & $Obj_Item.InfFileName & @CRLF $a_Text &= 'INF Section: ' & $Obj_Item.InfSection & @CRLF $a_Text &= 'Manufacturer: ' & $Obj_Item.Manufacturer & @CRLF $a_Text &= 'Name: ' & $Obj_Item.Name & @CRLF $a_Text &= 'Number Of Buttons: ' & $Obj_Item.NumberOfButtons & @CRLF $a_Text &= 'PNP Device ID: ' & $Obj_Item.PNPDeviceID & @CRLF $a_Text &= 'Pointing Type: ' & $Obj_Item.PointingType & @CRLF $a_Text &= 'Quad Speed Threshold: ' & $Obj_Item.QuadSpeedThreshold & @CRLF $a_Text &= 'Resolution: ' & $Obj_Item.Resolution & @CRLF $a_Text &= 'Sample Rate: ' & $Obj_Item.SampleRate & @CRLF $a_Text &= 'Synch: ' & $Obj_Item.Synch Next Return String($a_Text) Else Return 0 EndIf EndFunc Func _Processor_Speed() Local $s_Text = '' Dim $Obj_WMIService = ObjGet('winmgmts:\\' & @ComputerName & '\root\cimv2'); If (IsObj($Obj_WMIService)) And (Not @error) Then Dim $Col_Items = $Obj_WMIService.ExecQuery('Select * from Win32_Processor') Local $Obj_Item For $Obj_Item In $Col_Items Local $s_Text = 'Processor Id: ' & $Obj_Item.ProcessorId & @CRLF $s_Text &= 'Maximum Clock Speed: ' & $Obj_Item.MaxClockSpeed Next Return String($s_Text) Else Return 0 EndIf EndFunc Func _Computer_Type() Local $u_Text = '' Dim $Obj_WMIService = ObjGet('winmgmts:{impersonationLevel=impersonate}!\\' & @ComputerName & '\root\cimv2'); If (IsObj($Obj_WMIService)) And (Not @error) Then Dim $Col_Chassis = $Obj_WMIService.ExecQuery('Select * from Win32_SystemEnclosure') Local $Obj_Chassis For $Obj_Chassis In $Col_Chassis Local $Obj_Items For $Obj_Item In $Obj_Chassis.ChassisTypes If (Number($Obj_Item) = 1) Then Local $u_Text = 'Type: Other' & @CRLF ElseIf (Number($Obj_Item) = 2) Then Local $u_Text = 'Type: Unknown' & @CRLF ElseIf (Number($Obj_Item) = 3) Then Local $u_Text = 'Type: Desktop' & @CRLF ElseIf (Number($Obj_Item) = 4) Then Local $u_Text = 'Type: Low profile Desktop' & @CRLF ElseIf (Number($Obj_Item) = 5) Then Local $u_Text = 'Type: Pizza Box' & @CRLF ElseIf (Number($Obj_Item) = 6) Then Local $u_Text = 'Type: Mini Tower' & @CRLF ElseIf (Number($Obj_Item) = 7) Then Local $u_Text = 'Type: Tower' & @CRLF ElseIf (Number($Obj_Item) = 8) Then Local $u_Text = 'Type: Portable' & @CRLF ElseIf (Number($Obj_Item) = 9) Then Local $u_Text = 'Type: Laptop' & @CRLF ElseIf (Number($Obj_Item) = 10) Then Local $u_Text = 'Type: Notebook' & @CRLF ElseIf (Number($Obj_Item) = 11) Then Local $u_Text = 'Type: Hand Held' & @CRLF ElseIf (Number($Obj_Item) = 12) Then Local $u_Text = 'Type: Docking Station' & @CRLF ElseIf (Number($Obj_Item) = 13) Then Local $u_Text = 'Type: All in One' & @CRLF ElseIf (Number($Obj_Item) = 14) Then Local $u_Text = 'Type: Sub Notebook' & @CRLF ElseIf (Number($Obj_Item) = 15) Then Local $u_Text = 'Type: Space saving' & @CRLF ElseIf (Number($Obj_Item) = 16) Then Local $u_Text = 'Type: Lunch Box' & @CRLF ElseIf (Number($Obj_Item) = 17) Then Local $u_Text = 'Type: Main System Chassis' & @CRLF ElseIf (Number($Obj_Item) = 18) Then Local $u_Text = 'Type: Expansion Chassis' & @CRLF ElseIf (Number($Obj_Item) = 19) Then Local $u_Text = 'Type: SubChassis' & @CRLF ElseIf (Number($Obj_Item) = 20) Then Local $u_Text = 'Type: Bus Expansion Chassis' & @CRLF ElseIf (Number($Obj_Item) = 21) Then Local $u_Text = 'Type: Peripheral Chassis' & @CRLF ElseIf (Number($Obj_Item) = 22) Then Local $u_Text = 'Type: Storage Chassis' & @CRLF ElseIf (Number($Obj_Item) = 23) Then Local $u_Text = 'Type: Rack Mount Chassis' & @CRLF ElseIf (Number($Obj_Item) = 24) Then Local $u_Text = 'Type: Sealed-Case PC' & @CRLF Else Local $u_Text = 'Type: Unable to retrieve' & @CRLF EndIf Next ; Might not work properly $u_Text &= 'Name: ' & $Obj_Chassis.Name & @CRLF $u_Text &= 'Caption: ' & $Obj_Chassis.Caption & @CRLF $u_Text &= 'Manufacturer: ' & $Obj_Chassis.Manufacturer & @CRLF $u_Text &= 'Model: ' & $Obj_Chassis.Model & @CRLF $u_Text &= 'Description: ' & $Obj_Chassis.Description & @CRLF $u_Text &= 'Height: ' & $Obj_Chassis.Height & @CRLF $u_Text &= 'Width: ' & $Obj_Chassis.Width & @CRLF $u_Text &= 'Weight: ' & $Obj_Chassis.Weight & @CRLF $u_Text &= 'Depth: ' & $Obj_Chassis.Depth & @CRLF $u_Text &= 'Heat Generation: ' & $Obj_Chassis.HeatGeneration & @CRLF $u_Text &= 'Install Date: ' & $Obj_Chassis.InstallDate & @CRLF Next Return String($u_Text) Else Return 0 EndIf EndFunc Func _Physical_RAM_Available() Local $y_Text = '' Dim $Obj_WMIService = ObjGet('winmgmts:{impersonationLevel=impersonate}!\\' & @ComputerName & '\root\cimv2'); If (IsObj($Obj_WMIService)) And (Not @error) Then Dim $Col_Items = $Obj_WMIService.ExecQuery('Select * from Win32_ComputerSystem') Local $Obj_Items For $Obj_Items In $Col_Items Local $y_Text = 'RAM: ' & Round((($Obj_Items.TotalPhysicalMemory / 1024) / 1024), 3) & ' MB' Next Return String($y_Text) Else Return 0 EndIf EndFunc Func _Number_Of_Processors() Local $z_Text = '' Dim $Obj_WMIService = ObjGet('winmgmts:{impersonationLevel=impersonate}!\\' & @ComputerName & '\root\cimv2'); If (IsObj($Obj_WMIService)) And (Not @error) Then Dim $Col_Items = $Obj_WMIService.ExecQuery('Select * from Win32_ComputerSystem') Local $Obj_Items For $Obj_Items In $Col_Items Local $z_Text = 'Found: ' & $Obj_Items.NumberOfProcessors & ' processor(s)' Next Return String($z_Text) Else Return 0 EndIf EndFunc Func _Drives_Determine() Local $Columns = 4 Local $Number_DRV = DriveGetDrive('CDROM') Local $Drives[($Number_DRV[0] + 1)][$Columns] $Drives[0][0] = -1 Dim $Obj_WMIService = ObjGet('winmgmts:\\' & @ComputerName & '\root\cimv2'); If (IsObj($Obj_WMIService)) And (Not @error) Then Dim $Col_Items = $Obj_WMIService.ExecQuery('Select * from Win32_CDROMDrive') Local $Obj_Items For $Obj_Items In $Col_Items $Drives[0][0] += 1 $Drives[Number($Drives[0][0] + 1)][0] = $Obj_Items.DeviceID $Drives[Number($Drives[0][0] + 1)][1] = $Obj_Items.Description $Drives[Number($Drives[0][0] + 1)][2] = $Obj_Items.Name $Drives[Number($Drives[0][0] + 1)][3] = $Obj_Items.Drive Next $Drives[0][0] += 1 Return $Drives Else Return 0 EndIf EndFunc Func _USB_Devices() Local $Columns = 3 Local $usb_Array[9][$Columns] $usb_Array[0][0] = -1 Dim $Obj_WMIService = ObjGet('winmgmts:\\' & @ComputerName & '\root\cimv2'); If (IsObj($Obj_WMIService)) And (Not @error) Then Dim $Col_Items = $Obj_WMIService.ExecQuery('Select * from Win32_USBHub') Local $Obj_Items For $Obj_Items In $Col_Items $usb_Array[0][0] += 1 $usb_Array[Number($usb_Array[0][0] + 1)][0] = $Obj_Items.DeviceID $usb_Array[Number($usb_Array[0][0] + 1)][1] = $Obj_Items.PNPDeviceID $usb_Array[Number($usb_Array[0][0] + 1)][2] = $Obj_Items.Description If (($Obj_Items.Description) <> ($Obj_Items.Name)) Then ReDim $usb_Array[Number($usb_Array[0][0] + 1)][$Columns + 1] $usb_Array[Number($usb_Array[0][0] + 1)][3] = $Obj_Items.Name EndIf Next $usb_Array[0][0] += 1 Return $usb_Array Else Return 0 EndIf EndFunc Func _Check_Floppy() Local $m_Text = '' Dim $Obj_WMIService = ObjGet('winmgmts:\\' & @ComputerName & '\root\cimv2'); If (IsObj($Obj_WMIService)) And (Not @error) Then Dim $Col_Items = $Obj_WMIService.ExecQuery("Select * From Win32_LogicalDisk Where DeviceID = 'A:'") For $Obj_Items In $Col_Items Local $IntFreeSpace = $Obj_Items.FreeSpace If (IsNull($IntFreeSpace)) Then Local $m_Text = 'No disk in floppy drive.' Else Local $m_Text = 'Disk found in the floppy drive.' EndIf Next Return String($m_Text) Else Return 0 EndIf EndFunc Func _Office_GetVersion() Local $h_Text = '' Dim $Obj_WMIService = ObjGet('winmgmts:{impersonationLevel=impersonate}!\\' & @ComputerName & '\root\cimv2'); If (IsObj($Obj_WMIService)) And (Not @error) Then Dim $Col_Items = $Obj_WMIService.ExecQuery('Select * from Win32_Product ' & _ 'Where IdentifyingNumber =' _ & " '{90280409-6000-11D3-8CFE-0050048383C9}'") Local $Obj_Items For $Obj_Items In $Col_Items Local $h_Text = 'Name: ' & $Obj_Items.Name & @CRLF $h_Text &= 'Version: ' & $Obj_Items.Version Next Return String($h_Text) Else Return 0 EndIf EndFunc Func _Get_Startup_Services() Local $Columns = 6 Local $Startup_Services_Array[2][$Columns] $Startup_Services_Array[0][0] = 0 Dim $Obj_WMIService = ObjGet('winmgmts:{impersonationLevel=impersonate}!\\' & @ComputerName & '\root\cimv2'); If (IsObj($Obj_WMIService)) And (Not @error) Then Dim $Col_Items = $Obj_WMIService.ExecQuery('Select * from Win32_StartupCommand') Local $Obj_Items For $Obj_Items In $Col_Items $Startup_Services_Array[0][0] += 1 $Startup_Services_Array[Number($Startup_Services_Array[0][0])][0] = $Obj_Items.Command $Startup_Services_Array[Number($Startup_Services_Array[0][0])][1] = $Obj_Items.Description $Startup_Services_Array[Number($Startup_Services_Array[0][0])][2] = $Obj_Items.Location $Startup_Services_Array[Number($Startup_Services_Array[0][0])][3] = $Obj_Items.Name $Startup_Services_Array[Number($Startup_Services_Array[0][0])][4] = $Obj_Items.SettingID $Startup_Services_Array[Number($Startup_Services_Array[0][0])][5] = $Obj_Items.User ReDim $Startup_Services_Array[Number($Startup_Services_Array[0][0] + 2)][$Columns] Next $Startup_Services_Array[0][0] += 1 Return $Startup_Services_Array Else Return 0 EndIf EndFunc Func _Determine_Operating_System_Status() Local $j_Text = '' Dim $Obj_WMIService = ObjGet('winmgmts:{impersonationLevel=impersonate}!\\' & @ComputerName & '\root\cimv2'); If (IsObj($Obj_WMIService)) And (Not @error) Then Dim $Col_Items = $Obj_WMIService.ExecQuery('Select * from Win32_WindowsProductActivation') Local $Obj_Items For $Obj_Items In $Col_Items Global $Active_Require = $Obj_Items.ActivationRequired Switch $Active_Require Case 0 Local $j_Text = 'Activation Not Required' & @CRLF Case 1 Local $j_Text = 'Activation Is Required' & @CRLF Case Else Local $j_Text = 'unknown' & @CRLF EndSwitch $j_Text &= 'Remaining Evaluation Period (in days): ' & $Obj_Items.RemainingEvaluationPeriod & @CRLF $j_Text &= 'Remaining Grace Period: (in days): ' & $Obj_Items.RemainingGracePeriod Next Return String($j_Text) Else Return 0 EndIf EndFunc Func _Retrieve_Date_And_Time() Local $t_Text = '' Dim $Obj_WMIService = ObjGet('winmgmts:{impersonationLevel=impersonate}!\\' & @ComputerName & '\root\cimv2'); If (IsObj($Obj_WMIService)) And (Not @error) Then Dim $Col_Items = $Obj_WMIService.ExecQuery('Select * from Win32_LocalTime') Local $Obj_Items For $Obj_Items In $Col_Items Local $t_Text = 'Day: ' & $Obj_Items.Day & @CRLF $t_Text &= 'Day Of Week: ' & $Obj_Items.DayOfWeek & @CRLF $t_Text &= 'Hour: ' & $Obj_Items.Hour & @CRLF $t_Text &= 'Minute: ' & $Obj_Items.Minute & @CRLF $t_Text &= 'Month: ' & $Obj_Items.Month & @CRLF $t_Text &= 'Quarter: ' & $Obj_Items.Quarter & @CRLF $t_Text &= 'Second: ' & $Obj_Items.Second & @CRLF $t_Text &= 'Week In Month: ' & $Obj_Items.WeekInMonth & @CRLF $t_Text &= 'Year: ' & $Obj_Items.Year Next Return String($t_Text) Else Return 0 EndIf EndFunc Func _Get_Time_Zone() Local $l_Text = '' Dim $Obj_WMIService = ObjGet('winmgmts:\\' & @ComputerName & '\root\cimv2'); If (IsObj($Obj_WMIService)) And (Not @error) Then Dim $Col_Items = $Obj_WMIService.ExecQuery('Select * from Win32_TimeZone') Local $Obj_Items For $Obj_Items In $Col_Items Local $l_Text = 'Description: ' & $Obj_Items.Description & @CRLF $l_Text &= 'Daylight Name: ' & $Obj_Items.DaylightName & @CRLF $l_Text &= 'Standard Name: ' & $Obj_Items.StandardName Next Return String($l_Text) Else Return 0 EndIf EndFunc Func _Get_Username() Local $p_Text = '' Dim $Obj_WMIService = ObjGet('winmgmts:{impersonationLevel=impersonate}!\\' & @ComputerName & '\root\cimv2'); If (IsObj($Obj_WMIService)) And (Not @error) Then Dim $Col_Items = $Obj_WMIService.ExecQuery('Select * from Win32_ComputerSystem') Local $Obj_Items For $Obj_Items In $Col_Items Local $p_Text = 'Name: ' & $Obj_Items.Name & @CRLF $p_Text &= 'Username: ' & $Obj_Items.Username Next Return String($p_Text) Else Return 0 EndIf EndFunc Func _Get_Local_Accounts() Local $Columns = 4 Local $Local_Accounts_Array[2][$Columns] $Local_Accounts_Array[0][0] = 0 Dim $Obj_WMIService = ObjGet('winmgmts:\\' & @ComputerName & '\root\cimv2'); If (IsObj($Obj_WMIService)) And (Not @error) Then Dim $Col_Items = $Obj_WMIService.ExecQuery('Select * from Win32_Group Where LocalAccount = True') Local $Obj_Items For $Obj_Items In $Col_Items $Local_Accounts_Array[0][0] += 1 $Local_Accounts_Array[Number($Local_Accounts_Array[0][0])][0] = $Obj_Items.Name $Local_Accounts_Array[Number($Local_Accounts_Array[0][0])][1] = $Obj_Items.Sid Local $Sz_SetType = Number($Obj_Items.SidType) Select Case $Sz_SetType = 1 $Local_Accounts_Array[Number($Local_Accounts_Array[0][0])][2] = 'User' Case $Sz_SetType = 2 $Local_Accounts_Array[Number($Local_Accounts_Array[0][0])][2] = 'Group' Case $Sz_SetType = 3 $Local_Accounts_Array[Number($Local_Accounts_Array[0][0])][2] = 'Domain' Case $Sz_SetType = 4 $Local_Accounts_Array[Number($Local_Accounts_Array[0][0])][2] = 'Alias' Case $Sz_SetType = 5 $Local_Accounts_Array[Number($Local_Accounts_Array[0][0])][2] = 'Well Known Group' Case $Sz_SetType = 6 $Local_Accounts_Array[Number($Local_Accounts_Array[0][0])][2] = 'Deleted Account' Case $Sz_SetType = 7 $Local_Accounts_Array[Number($Local_Accounts_Array[0][0])][2] = 'Invalid' Case $Sz_SetType = 8 $Local_Accounts_Array[Number($Local_Accounts_Array[0][0])][2] = 'Unknown' Case $Sz_SetType = 9 $Local_Accounts_Array[Number($Local_Accounts_Array[0][0])][2] = 'Computer' EndSelect $Local_Accounts_Array[Number($Local_Accounts_Array[0][0])][3] = $Obj_Items.Status ReDim $Local_Accounts_Array[Number($Local_Accounts_Array[0][0] + 2)][$Columns] Next Return $Local_Accounts_Array Else Return 0 EndIf EndFunc Func _Get_Events_From_Log() Local $Columns = 9 Local $Events_Array[2][$Columns] $Events_Array[0][0] = 0 Dim $Obj_WMIService = ObjGet('winmgmts:{impersonationLevel=impersonate}!\\' & @ComputerName & '\root\cimv2'); If (IsObj($Obj_WMIService)) And (Not @error) Then Dim $Col_Items = $Obj_WMIService.ExecQuery("Select * from Win32_NTLogEvent " _ & "Where Logfile = 'System'") Local $Obj_Items For $Obj_Items In $Col_Items $Events_Array[0][0] += 1 $Events_Array[Number($Events_Array[0][0])][0] = $Obj_Items.Category $Events_Array[Number($Events_Array[0][0])][1] = $Obj_Items.ComputerName $Events_Array[Number($Events_Array[0][0])][2] = $Obj_Items.EventCode $Events_Array[Number($Events_Array[0][0])][3] = $Obj_Items.Message $Events_Array[Number($Events_Array[0][0])][4] = $Obj_Items.RecordNumber $Events_Array[Number($Events_Array[0][0])][5] = $Obj_Items.SourceName $Events_Array[Number($Events_Array[0][0])][6] = $Obj_Items.TimeWritten $Events_Array[Number($Events_Array[0][0])][7] = $Obj_Items.Type $Events_Array[Number($Events_Array[0][0])][8] = $Obj_Items.User ReDim $Events_Array[Number($Events_Array[0][0] + 2)][$Columns] Next Return $Events_Array Else Return 0 EndIf EndFunc Func _Rename_Computer($iName = @ComputerName) Local $z_Text = '' Dim $Obj_WMIService = ObjGet('winmgmts:{impersonationLevel=impersonate}!\\' & @ComputerName & '\root\cimv2'); If (IsObj($Obj_WMIService)) And (Not @error) Then Dim $Col_Items = $Obj_WMIService.ExecQuery('Select * from Win32_ComputerSystem') Local $Obj_Items For $Obj_Items In $Col_Items Local $z_Text = $Obj_Items.Rename(String($iName)) Next EndIf EndFunc ; Logic IsNull() expression [http://msdn2.microsoft.com/en-us/library/zbchw6hz.aspx] Func IsNull($g_Var) If ((String($g_Var) == '') Or (IsBinary($g_Var)) Or (Not String($g_Var)) Or (StringIsSpace($g_Var)) Or (@error)) Then Return True Else Return False EndIf EndFunc ps: _Get_Startup_Services() And _Get_Events_From_Log() will take a long time to be executed.
    1 point
  4. Is it possible to pass a native AutoIt array as a parameter to a function coded in assembler, C, C++, C# or FreeBasic? And how is this possible? That's what this example is about. If possible, it may increase the performance of array manipulations significantly through fast functions of compiled code. The very, very short answers to the two questions above are: Yes. And through COM objects. Here is a small example that shows what it's all about. You can find the example in zip file in bottom of post (goto top of second post and scroll up a little bit). ;#AutoIt3Wrapper_UseX64=y #include "Includes\AccVarsUtilities.au3" #include "Includes\InspectVariable.au3" #include "Includes\ArrayDisplayEx.au3" #include "Includes\FasmUtils.au3" Opt( "MustDeclareVars", 1 ) Example() Func Example() ; === UDF and flat assembler (fasm) code === Local $hTimer1 = TimerInit() ; --- Create and fill safearray --- ; Create safearray Local $tSafeArrayBound = DllStructCreate( $tagSAFEARRAYBOUND ) DllStructSetData( $tSafeArrayBound, "cElements", 2^24 ) ; Number of elements in array DllStructSetData( $tSafeArrayBound, "lLbound", 0 ) ; Lower bound of array index Local $pSafeArray = SafeArrayCreate( $VT_I4, 1, $tSafeArrayBound ) ConsoleWrite( @CRLF & "--- Inspect safearray ---" & @CRLF ) InspectSafeArray( $pSafeArray ) ; Pointer to data Local $pSafeArrayData SafeArrayAccessData( $pSafeArray, $pSafeArrayData ) ; AutoIt code ;For $i = 0 To 2^24 - 1 ; DllStructSetData( $tSafeArrayData, 1, $i, $i + 1 ) ;Next ; <<<< Execute your assembler, C, C++, C# or FreeBasic code at this point >>>> ; Get fasm code Local $sFasmCode = @AutoItX64 ? "0xB80000000089024883C204FFC0E2F6C3" _ ; Example-x64.asm : "0x5589E58B4D088B550CB800000000890283C20440E2F85DC20800" ; Example-x86.asm Local $pFasmCode = FasmGetBinaryString( $sFasmCode, 64 ) If Not $pFasmCode Then Return ConsoleWrite( "$pFasmCode ERR" & @CRLF ) ; Execute fasm code to fill safearray DllCallAddress( "int", $pFasmCode, "int", 2^24, "ptr", $pSafeArrayData ) SafeArrayUnaccessData( $pSafeArray ) ; --- Convert safearray to native AutoIt array --- Local $aArray1 AccVars_SafeArrayToArray( $pSafeArray, $aArray1 ) ; <<<< The UDF >>>> ConsoleWrite( @CRLF & "Applied time to create and fill array (UDF and fasm): " & TimerDiff( $hTimer1 ) & @CRLF ) ; ------------------------------------------------ _ArrayDisplayEx( $aArray1, Default, "", 0x0010, "", "", "", 75 ) ConsoleWrite( @CRLF & "--- Inspect $aArray1 ---" & @CRLF ) InspectArray( $aArray1 ) $aArray1 = 0 ; === Pure AutoIt code === ConsoleWrite( @CRLF & "Executing pure AutoIt code to create and fill array (~10 seconds) ..." & @CRLF ) Local $hTimer2 = TimerInit() Local $aArray2[2^24] For $i = 0 To 2^24 - 1 $aArray2[$i] = $i Next ConsoleWrite( @CRLF & "Applied time to create and fill array (pure AutoIt): " & TimerDiff( $hTimer2 ) & @CRLF ) _ArrayDisplayEx( $aArray2, Default, "", 0x0010, "", "", "", 75 ) ConsoleWrite( @CRLF & "--- Inspect $aArray2 ---" & @CRLF ) InspectArray( $aArray2 ) $aArray2 = 0 EndFunc Line 53 is the crucial line of code: AccVars_SafeArrayToArray( $pSafeArray, $aArray1 ) ; <<<< The UDF >>>> Output in SciTE console should look like this: --- Inspect safearray --- Number of dimensions = 1 Features flags = 0x00000080 ($FADF_HAVEVARTYPE, array of variant type) Variant type = 0x0003 (VT_I4, 4 bytes signed integer) Size of array element (bytes) = 4 (size of the element structure) Number of locks = 0 Pointer to data = 0x02B80020 (pvData) Dimension 1: Elements in dimension = 16777216 Lower bound of dimension = 0 Applied time to create and fill array (UDF and fasm): 797.855906880413 --- Inspect $aArray1 --- Number of dimensions = 1 Features flags = 0x00000880 ($FADF_VARIANT+$FADF_HAVEVARTYPE, array of variants) Variant type = 0x000C (VT_VARIANT, variant data type) Size of array element (bytes) = 16 (size of the variant structure) Number of locks = 0 Pointer to data = 0x7FFF0020 (pvData) Dimension 1: Elements in dimension = 16777216 Lower bound of dimension = 0 Executing pure AutoIt code to create and fill array (~10 seconds) ... Applied time to create and fill array (pure AutoIt): 8670.46279987079 --- Inspect $aArray2 --- Number of dimensions = 1 Features flags = 0x00000880 ($FADF_VARIANT+$FADF_HAVEVARTYPE, array of variants) Variant type = 0x000C (VT_VARIANT, variant data type) Size of array element (bytes) = 16 (size of the variant structure) Number of locks = 0 Pointer to data = 0x7FFF0020 (pvData) Dimension 1: Elements in dimension = 16777216 Lower bound of dimension = 0 The UDF and fasm code is about 10 times faster than the pure AutoIt code. The code to populate the array is very simple. That's why the AutoIt code is doing relatively well compared to the UDF and fasm code. The technique implemented here can also be used to pass simple AutoIt variables to a function coded in a another language. This makes it possible to test on simple variables, rather than more complex arrays. And simple variables are needed in the final UDF. Post 7 contains a brief description of how the idea for this project arose. You'll find the following sections below: Accessing variables COM objects - COM objects can handle AutoIt arrays. Can this be exploited? AccessingVariablesTest.au3 - Test with UIAutomation::RectToVariant (Examples - Tests\Examples\0) Accessing variables\) Simple variables Variants - Introduction Basic strings - Introduction Examples - Tests\Examples\1) Simple variables\ Numeric variables (post 11) Numeric variants (post 11) Array variables Safearrays - Introduction Examples - Tests\Examples\2) Array variables\ Assembler code SafeArrayDisplay.au3 (post 24) Safearrays of integers (post 24) Internal conversions Exploiting conversions Avoiding conversions (Examples - Tests\Examples\3) Internal conversions\) Limitations (post 13) Final UDF - AccessingVariables.au3 AccessVariablesXY - 30 functions Restrictions - No literal params, no nested funcs Utility funcs - AccVarsUtilities.au3 InspectVariable - InspectVariable.au3 Using the UDF - Examples\Demo examples\4) Other demo examples\6) Using the UDF\ Subclassing (post 21) - Examples\Subclassing\ Examples Demo examples - Examples\Demo examples\ Assembler code - Tools to create fasm code not included Other demo examples - Examples\Demo examples\4) Other demo examples\ Real examples - Examples\Real examples\ sqlite3_get_table (post 25) What's next (post 26) Zip file For tests and for implementing the final UDF I've copied code written by monoceres, I've copied code from AutoItObject.au3 by the AutoItObject-Team: monoceres, trancexx, Kip, ProgAndy, and from CUIAutomation2.au3 by junkew. Lots of credit to these guys. Accessing variables AutoIt is a BASIC-like language. In BASIC-like languages simple variables are internally stored as variants, and arrays are internally stored as safearrays contained in variants. Assuming that an AutoIt variable is internally stored as a variant, is it possible to get a pointer to this variant? Assuming that an AutoIt array is internally stored as a safearray contained in a variant, then it should be possible to get a pointer to the safearray through the pointer to the variant. Why is a pointer to a safearray interesting? Because such a pointer can be passed as a parameter to a function coded in assembler, C, C++, C# or FreeBasic. We can thus access an AutoIt array directly from a function coded in another language, without the need to convert the array to a structure (DllStructCreate) or similar. In this way it's possible to code very fast array manipulation functions in a real compiled language. The crucial step is to get a pointer to the variant that contains the variable or array. COM objects If you have been using COM objects like the Dictionary ("Scripting.Dictionary") object, you know that this object can return AutoIt arrays in this way: $aKeys = $oDict.Keys() $aItems = $oDict.Items() In an example in "Obj/COM Reference" chapter in AutoIt Help file you can find this code line: $oExcel.activesheet.range("A1:O16").value = $aArray ; Fill cells with example numbers The Excel object seems to know how to handle a native AutoIt array. For objects created with ObjCreateInterface it's also easy to find examples where these objects understands how to handle native AutoIt arrays. An example is RectToVariant method of the UIAutomation object. This method converts a rectangle structure to an array: ; Create UIAutomation object Local $oUIAutomation = ObjCreateInterface( $sCLSID_CUIAutomation, $sIID_IUIAutomation, $stag_IUIAutomation ) If Not IsObj( $oUIAutomation ) Then Return ConsoleWrite( "$oUIAutomation ERR" & @CRLF ) ConsoleWrite( "$oUIAutomation OK" & @CRLF ) ; Create rectangle structure Local $tRect = DllStructCreate( $tagRECT ) DllStructSetData( $tRect, "Left", 100 ) DllStructSetData( $tRect, "Top", 200 ) DllStructSetData( $tRect, "Right", 3000 ) DllStructSetData( $tRect, "Bottom", 4000 ) Local $aArray $oUIAutomation.RectToVariant( $tRect, $aArray ) ; Variant array: VT_ARRAY + VT_R8 If Not IsArray( $aArray ) Then Return ConsoleWrite( "$aArray ERR" & @CRLF ) ConsoleWrite( "$aArray OK" & @CRLF ) _ArrayDisplay( $aArray ) You can find the example (Tests\Examples\0) Accessing variables\Example1.au3) in the zip below. AccessingVariablesTest.au3 I've been playing with RectToVariant method of the UIAutomation object. And I have studied how the output array ($aArray in the code above) looks like in C++ (see also last code box in post 15). The description for RectToVariant in $stag_IUIAutomation looks like this: "RectToVariant hresult(" & ( @AutoItX64 ? "struct*;" : "struct;" ) & "variant*);" Note the last parameter "variant*". What's that? That's a pointer to a variant. Exactly what we need. You can get a pointer to the variant that contains $aArray in the example above in this way: Replace the RectToVariant method with your own function. Inside the function the pointer to the variant that contains $aArray is simply the last parameter. It's necessary to replace RectToVariant with our own function to be able to add code inside the function. And it's very important that the parameter type in the function (or method) description string is "variant*". Exactly this parameter type ensures that the parameter coming from the AutoIt code is converted to a pointer to a variant. Inside the RectToVariant method or our own function the last parameter is not a native AutoIt array. It's a pointer to a variant. This conversion between different data types is performed by internal AutoIt code. And the conversion is only performed in relation to objects. There is no such conversion in relation to eg. the DllCall function. That's why we have to deal with objects. The technique of replacing an object method with our own function has been seen many times before. Eg. in this old example by monoceres. Now when we have ObjCreateInterface it's much easier. You don't need much code: #include-once #include "..\Includes\Variant.au3" #include "..\Includes\SafeArray.au3" #include "..\Includes\Utilities.au3" Global $hAccessVariableFunction Func AccessVariable( $hAccessVariableFunc, ByRef $vVariable ) Static $oAccessVariable = AccessVariableInit() ; Init $oAccessVariable (only once) $hAccessVariableFunction = $hAccessVariableFunc ; Code to execute in VariableToVariant $oAccessVariable.VariableToVariant( $vVariable ) ; Execute VariableToVariant method EndFunc Func AccessVariableInit() ; Three locals copied from "IUIAutomation MS framework automate chrome, FF, IE, ...." by junkew ; https://www.autoitscript.com/forum/index.php?showtopic=153520 Local $sCLSID_CUIAutomation = "{FF48DBA4-60EF-4201-AA87-54103EEF594E}" Local $sIID_IUIAutomation = "{30CBE57D-D9D0-452A-AB13-7AC5AC4825EE}" Local $stag_IUIAutomation = _ "f01 hresult();f02 hresult();f03 hresult();f04 hresult();f05 hresult();f06 hresult();f07 hresult();" & _ "f08 hresult();f09 hresult();f10 hresult();f11 hresult();f12 hresult();f13 hresult();f14 hresult();" & _ "f15 hresult();f16 hresult();f17 hresult();f18 hresult();f19 hresult();f20 hresult();f21 hresult();" & _ "f22 hresult();f23 hresult();f24 hresult();f25 hresult();f26 hresult();f27 hresult();f28 hresult();" & _ "f29 hresult();f30 hresult();f31 hresult();f32 hresult();f33 hresult();f34 hresult();f35 hresult();" & _ "f36 hresult();f37 hresult();f38 hresult();f39 hresult();f40 hresult();f41 hresult();" & _ "VariableToVariant hresult(variant*);" & _ ; "RectToVariant hresult(" & ( @AutoItX64 ? "struct*;" : "struct;" ) & "variant*);" "f43 hresult();f44 hresult();f45 hresult();f46 hresult();f47 hresult();f48 hresult();f49 hresult();" & _ "f50 hresult();f51 hresult();f52 hresult();f53 hresult();f54 hresult();f55 hresult();" ; Create AccessVariable object (Automation object) Local $oAccessVariable = ObjCreateInterface( $sCLSID_CUIAutomation, $sIID_IUIAutomation, $stag_IUIAutomation ) If Not IsObj( $oAccessVariable ) Then Return SetError(1,0,1) ; Replace RectToVariant method with VariableToVariant method Local $pVariableToVariant = DllCallbackGetPtr( DllCallbackRegister( "VariableToVariant", "long", "ptr;ptr*" ) ) ReplaceVTableFuncPtr( Ptr( $oAccessVariable() ), ( 3 + 42 - 1 ) * ( @AutoItX64 ? 8 : 4 ), $pVariableToVariant ) Return $oAccessVariable EndFunc Func VariableToVariant( $pSelf, $pVariant ) $hAccessVariableFunction( $pVariant ) Return 0 ; $S_OK (COM constant) #forceref $pSelf EndFunc The code is saved in Tests\AccessingVariablesTest.au3 in the zip. To use the UDF you call AccessVariable function in the top. Note the ByRef keyword in the function. The ByRef keyword is very important. The function will not work without this keyword. Note also that the pointer to the variant in VariableToVariant function in bottom of the UDF is created by some internal AutoIt conversion code. And it's a local function parameter. The pointer is only valid within VariableToVariant and in the function you specify as a parameter when you call AccessVariable. As soon as VariableToVariant returns, the pointer is invalid. Let's try some small examples with simple variables and array variables. Simple variables Before we go to the examples let's take a quick look at variants and basic strings (BSTRs). Variants and basic strings are needed in our assembler, C, C++, C# or FreeBasic functions. Variants A variant is defined by this structure: Global Const $tagVARIANT = "word vt;word r1;word r2;word r3;ptr data; ptr" Only vt and data elements are used. The structure takes up 16/24 bytes when you're running 32/64 bit. Space for the data element at the end represents 2 pointers. This is 8/16 bytes when you're running 32/64 bit. If $pVariant is a pointer to a variant you can get vt and data elements in this way: Local $vt = DllStructGetData( DllStructCreate( "word", $pVariant ), 1 ) Local $data = DllStructGetData( DllStructCreate( "<vt>", $pVariant + 8 ), 1 ) The four word (word = 2 bytes) elements before the data element takes up 8 bytes. Common values of vt in AutoIt are: $VT_I4 = 3 ; Integer, "<vt>" = "int" $VT_R8 = 5 ; Double, "<vt>" = "double" $VT_BSTR = 8 ; Basic string, "<vt>" = "ptr" $VT_UI4 = 19 ; Pointer running 32 bit, "<vt>" = "ptr" $VT_UI8 = 21 ; Pointer running 64 bit, "<vt>" = "ptr" If $pVariant is a pointer to a variant which contains an array you'll always get this value for vt: $VT_ARRAY + $VT_VARIANT = 0x200C ; Pointer, "<vt>" = "ptr" A native AutoIt array is stored as a safearray ($VT_ARRAY = 0x2000) contained in a variant ($VT_VARIANT = 0x000C). The pointer to the safearray is stored in the data element of the variant. Variant constants and functions are defined in Includes\Variant.au3. Most of the code is shamelessly copied from AutoItObject.au3 by the AutoItObject-Team: monoceres, trancexx, Kip, ProgAndy. Basic strings Internally AutoIt strings are stored as basic strings or BSTRs. The pointer to the BSTR is stored in a variant. A BSTR is defined by this structure: Global Const $tagBSTR = & _ "dword Length;" & _ ; Length in bytes (2 * $iLen), does not include the Terminator "wchar String[" & $iLen & "];" & _ ; $iLen is wchars, $pBSTR = DllStructGetPtr( $tBSTR, "String" ) "word Terminator;" ; Two null characters Use this code to get the pointer to the BSTR (the pointer which is stored in a variant): Local $pBSTR = DllStructGetPtr( $tBSTR, "String" ) Note that the BSTR pointer is the start of the "String" element and not the start of the structure. Normally you do not handle BSTRs directly through this structure. You use the BSTR functions in Variant.au3. Also copied from AutoItObject.au3. You can find information about variant and BSTR conversion and manipulation functions here. Examples The examples are stored in "Tests\Examples\1) Simple variables\". There are three small examples. These examples are just AutoIt code. This is a part of Example2.au3: Local $sStr = "AutoIt" ConsoleWrite( "$sStr = " & $sStr & @CRLF ) AccessVariable( InspectVariableMtd, $sStr ) ; InspectVariableMtd is coded in Includes\InspectVariable.au3 AccessVariable( SetString, $sStr ) ; Shows how to use the AccessVariable function ConsoleWrite( "$sStr = " & $sStr & @CRLF ) Func SetString( $pVariant ) Local $pData = $pVariant + 8 ; See InspectVariable.au3 Local $tData = DllStructCreate( "ptr", $pData ) Local $pBStr = DllStructGetData( $tData, 1 ) SysFreeString( $pBStr ) ; See Variant.au3 $pBStr = SysAllocString( "Hello world" ) DllStructSetData( $tData, 1, $pBStr ) EndFunc The output i SciTE console should look like this: $sStr = AutoIt ptr = 0x006F9630 ($pVariant) vt = 0x0008 (VT_BSTR, basic string) data = AutoIt $sStr = Hello world Example3.au3 is similar to the example for VarGetType in the Help file. It prints the variant vt-values for the corresponding AutoIt data types. Array variables Before we go to the examples let's take a quick look at safearrays. Safearrays A safearray is defined by these structures: Global Const $tagSAFEARRAYBOUND = _ "ulong cElements;" & _ ; The number of elements in the dimension. "long lLbound;" ; The lower bound of the dimension. Global Const $tagSAFEARRAY = _ "ushort cDims;" & _ ; The number of dimensions. "ushort fFeatures;" & _ ; Flags, see below. "ulong cbElements;" & _ ; The size of an array element. "ulong cLocks;" & _ ; The number of times the array has been locked without a corresponding unlock. "ptr pvData;" & _ ; The data. $tagSAFEARRAYBOUND ; One $tagSAFEARRAYBOUND for each dimension. ; Examples ; 1D, 2D and 3D safearrays: Local $tagSAFEARRAY1D = $tagSAFEARRAY Local $tagSAFEARRAY2D = $tagSAFEARRAY & $tagSAFEARRAYBOUND Local $tagSAFEARRAY3D = $tagSAFEARRAY & $tagSAFEARRAYBOUND & $tagSAFEARRAYBOUND In AutoIt an array is stored as a safearray contained in a variant. The safearray is always an array of variants. That the safearray is contained in a variant means that the pointer to the safearray is stored in the data element of a variant. That the safearray is an array of variants means that the pvData element of the safearray points to a memory area which contains a continuous row of variant structures. If we're running 32 bit a variant takes up 16 bytes. For a 1D-array with three elements: Local $aArray[3] = [ 1, 2, 3 ] The pvData element of the safearray points to a memory area which takes up 48 bytes and consists of three variant structures. Normally you do not handle safearrays directly through these structures. You use the safearray functions in Includes\SafeArray.au3. Copied from AutoItObject.au3. You can find information about safearray conversion and manipulation functions here. Examples The examples are stored in "Tests\Examples\2) Array variables\". The examples are still just AutoIt code. Example1.au3 prints information for 1D-arrays of integers, floats and strings. Information for the integer array should look like this: $aInts = [ 0, 1, 2 ] --- InspectVariable $aInts --- ptr = 0x00990378 ($pVariant) vt = 0x200C (VT_ARRAY+VT_VARIANT, array of variants, safearray) data = 0x009981E8 (pointer to safearray) --- InspectVariable $aInts[0] --- ptr = 0x0098FEC8 ($pVariant) vt = 0x0003 (VT_I4, 4 bytes signed integer) data = 0 --- InspectArray $aInts --- Number of dimensions = 1 Features flags = 0x00000880 ($FADF_VARIANT+$FADF_HAVEVARTYPE, array of variants) Variant type = 0x000C (VT_VARIANT, variant data type) Size of array element (bytes) = 16 (size of the variant structure) Number of locks = 0 Pointer to data = 0x00998710 (pvData) Dimension 1: Elements in dimension = 3 Lower bound of dimension = 0 Example2.au3 prints information for 2D-arrays of integers, floats and strings, and prints the contents of the arrays through the data area of the safearray. pvData element of $tagSAFEARRAY structure is a pointer to the data area. Example3.au3 fills an existing array, $aArray[50000], with integers. Example4.au3 creates and fills an array with 50000 integers and assigns it to an uninitialized variable: $aArray (empty string). Assembler code Example5.au3 is the first small example with fasm code (fasm = flat assembler, more info about fasm in one of the next sections). A 1D-array with 2^24 (16,777,216) elements is filled with integers from zero to 2^24 - 1. The array is first filled through AutoIt code. Then AccessVariable is used to fill the corresponding safearray through fasm code. There are two versions of the fasm code: A 32 bit version and a 64 bit version. AutoIt code (Example5.au3): ;#AutoIt3Wrapper_UseX64=y #include "..\..\AccessingVariablesTest.au3" #include "..\..\..\Includes\ArrayDisplayEx.au3" #include "..\..\..\Includes\FasmUtils.au3" Opt( "MustDeclareVars", 1 ) Example5() Func Example5() ConsoleWrite( "Executing AutoIt code to fill array (~10 seconds) ..." & @CRLF ) Local $aArray1[2^24] ; 2^24 = 16,777,216, maximum number of elements for an array Local $hTimer1 = TimerInit() For $i = 0 To 2^24 - 1 $aArray1[$i] = $i Next ConsoleWrite( "Time for AutoIt code to fill array: " & TimerDiff( $hTimer1 ) & @CRLF & @CRLF ) _ArrayDisplayEx( $aArray1 ) $aArray1 = 0 ConsoleWrite( "Executing FillArray to fill array ..." & @CRLF ) Local $aArray2[2^24] ; 2^24 = 16,777,216, maximum number of elements for an array Local $hTimer4 = TimerInit() AccessVariable( FillArray, $aArray2 ) Local $fTime4 = TimerDiff( $hTimer4 ) ConsoleWrite( "Time for FillArray to fill array (outside FillArray): " & $fTime4 & @CRLF ) ConsoleWrite( "Time for FillArray to fill array: " & $fTime4 & @CRLF ) _ArrayDisplayEx( $aArray2 ) $aArray2 = 0 EndFunc Func FillArray( $pVariant ) Local $hTimer3 = TimerInit() ; Pointer to safearray Local $pData = $pVariant + 8 Local $tData = DllStructCreate( "ptr", $pData ) Local $pSafeArray = DllStructGetData( $tData, 1 ) ; Pointer to data Local $pSafeArrayData SafeArrayAccessData( $pSafeArray, $pSafeArrayData ) ; Get fasm code Static $sFasmCode = @AutoItX64 ? "0xB80000000066C70203008942084883C218FFC0E2F0C3" _ ; Example5-x64.asm : "0x5589E58B4D088B550CB80000000066C702030089420883C21040E2F25DC20800" ; Example5-x86.asm Static $pFasmCode = FasmGetBinaryString( $sFasmCode, 64 ) If Not $pFasmCode Then Exit ConsoleWrite( "$pFasmCode ERR" & @CRLF ) ; Execute fasm code Local $hTimer2 = TimerInit() DllCallAddress( "int", $pFasmCode, "int", 2^24, "ptr", $pSafeArrayData ) ConsoleWrite( "Time for FillArray to fill array (fasm code only): " & TimerDiff( $hTimer2 ) & @CRLF ) SafeArrayUnaccessData( $pSafeArray ) ConsoleWrite( "Time for FillArray to fill array (inside FillArray): " & TimerDiff( $hTimer3 ) & @CRLF ) EndFunc Note that the fasm code is executed inside FillArray function. And FillArray function is executed inside the $oAccessVariable.VariableToVariant method (in AccessingVariablesTest.au3). The pointer to the safearray data ($pSafeArrayData) is valid only inside this method. $pSafeArrayData is a pointer that points to the data area that contains the data of $aArray2. $pSafeArrayData however does not point directly to the same data as contained in $aArray2. Internal AutoIt conversions on function entry copies data from $aArray2 to the data area. Internal AutoIt conversions on function exit copies data from the data area to $aArray2. See next section. 32 bit fasm code (Example5-x86.asm): ; flat assembler code ; Translate AutoIt code to fasm code: ; For $i = 0 To 2^24 - 1 ; $aArray[$i] = $i ; Next ; Parameters: ; [ebp + 08] : iRows ; First parameter ; [ebp + 12] : pSafeArrayData ; Second parameter ; Init directive use32 ; 32 bit code ; Entry code push ebp ; Store base pointer on stack mov ebp, esp ; Use stack pointer as base pointer ; Function code mov ecx, [ebp + 08] ; ecx corresponds to 2^24 in "For $i = 0 To 2^24 - 1" mov edx, [ebp + 12] ; edx is pointer in safearray data area mov eax, 0 ; eax = 0, eax corresponds to $i iLoop: mov [edx], word 3 ; Set vt element in variant to 3 (VT_I4, integer) mov [edx + 08], eax ; Set data element in variant to eax ($i) add edx, 16 ; Add size of variant structure to edx inc eax ; eax += 1, corresponds to $i += 1 loop iLoop ; ecx -= 1, jump to iLoop if not zero ; Exit code pop ebp ; Restore base pointer from stack ret 08 ; Return and cleanup stack 64 bit fasm code (Example5-x64.asm): ; flat assembler code ; Translate AutoIt code to fasm code: ; For $i = 0 To 2^24 - 1 ; $aArray[$i] = $i ; Next ; Parameters: ; rcx : iRows ; First parameter, ecx corresponds to 2^24 in "For $i = 0 To 2^24 - 1" ; rdx : pSafeArrayData ; Second parameter, rdx is pointer in safearray data area ; Init directive use64 ; 64 bit code ; Function code mov eax, 0 ; eax = 0, eax corresponds to $i iLoop: mov [rdx], word 3 ; Set vt element in variant to 3 (VT_I4, integer) mov [rdx + 08], eax ; Set data element in variant to eax ($i) add rdx, 24 ; Add size of variant structure to rdx inc eax ; eax += 1, corresponds to $i += 1 loop iLoop ; ecx -= 1, jump to iLoop if not zero ; Exit code ret ; Return Output in SciTE console: Executing AutoIt code to fill array (~10 seconds) ... Time for AutoIt code to fill array: 9033.87383563625 Executing FillArray to fill array ... Time for FillArray to fill array (fasm code only): 28.5154490311906 Time for FillArray to fill array (inside FillArray): 28.6592369763861 Time for FillArray to fill array (outside FillArray): 2388.37594979003 Time for FillArray to fill array: 2388.37594979003 Why is there such a big difference in the time it takes to execute FillArray when the time is measured inside and outside the function? Internal conversions In "Obj/COM Reference" chapter, "COM Events" section and "Limitations on COM Events in AutoIt" subsection in AutoIt Help file you can find the following sentence: "... AutoIt uses its own variable scheme, which is not compatible to COM variables. This means that all values from Objects need to be converted into AutoIt variables ...". In the AutoIt website you can find small bits of information like this one. These internal conversions takes place between native AutoIt data types and COM data types, when AutoIt variables are passed to object methods as function parameters, and when COM variables are returned to AutoIt. There are two sets of conversions. Conversions on function entry (object method entry), and conversions on function exit. The previous section ended with this question: Why is there such a big difference in the time it takes to execute FillArray when the time is measured inside and outside the function (FillArray is executed inside the object method)? The large time difference is caused by the conversions. The conversions are performed by internal AutoIt code and Windows API functions. Both consists of compiled C++ code. Judging from the time the conversions takes (about 2.5 seconds on my PC), they seem to perform a complete (by value) copy of the entire array. The array with 16,777,216 integers. Even for compiled C++ code it takes time to copy such a large array. Example1.au3 ("Tests\Examples\3) Internal conversions\") shows how long time the conversions takes: ;#AutoIt3Wrapper_UseX64=y #include "..\..\AccessingVariablesTest.au3" #include "..\..\..\Includes\ArrayDisplayEx.au3" Opt( "MustDeclareVars", 1 ) Example1() Func Example1() ConsoleWrite( "Filling array of 16,777,216 integers (~10 seconds) ..." & @CRLF ) Local $aArray1[2^24] ; 2^24 = 16,777,216, maximum number of elements for an array For $i = 0 To 2^24 - 1 $aArray1[$i] = 1234 Next Local $hTimer = TimerInit() AccessVariable( ConversionTime, $aArray1 ) ConsoleWrite( "Time for conversion code to execute: " & TimerDiff( $hTimer ) & @CRLF & @CRLF ) _ArrayDisplayEx( $aArray1 ) $aArray1 = 0 ConsoleWrite( "Filling array of 16,777,216 doubles (~10 seconds) ..." & @CRLF ) Local $aArray2[2^24] ; 2^24 = 16,777,216, maximum number of elements for an array For $i = 0 To 2^24 - 1 $aArray2[$i] = 1234.5678 Next $hTimer = TimerInit() AccessVariable( ConversionTime, $aArray2 ) ConsoleWrite( "Time for conversion code to execute: " & TimerDiff( $hTimer ) & @CRLF & @CRLF ) _ArrayDisplayEx( $aArray2 ) $aArray2 = 0 ConsoleWrite( "Filling array of 1,048,576 100-chars strings (~5 seconds) ..." & @CRLF ) Local $aArray3[2^20] ; 2^20 = 1,048,576 For $i = 0 To 2^20 - 1 $aArray3[$i] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ; 100 chars Next $hTimer = TimerInit() AccessVariable( ConversionTime, $aArray3 ) ConsoleWrite( "Time for conversion code to execute: " & TimerDiff( $hTimer ) & @CRLF ) _ArrayDisplayEx( $aArray3 ) $aArray3 = 0 EndFunc ; Because this is an empty function the time measured above ; is the total time for all conversions of one array parameter. Func ConversionTime( $pVariant ) EndFunc Output in SciTE console: Filling array of 16,777,216 integers (~10 seconds) ... Time for conversion code to execute: 4303.24786930952 Filling array of 16,777,216 doubles (~10 seconds) ... Time for conversion code to execute: 4341.52716013949 Filling array of 1,048,576 100-chars strings (~5 seconds) ... Time for conversion code to execute: 2416.14925416137 Because 16,777,216 elements is the maximum number of elements in an array, the conversions will never take longer than 4.5 seconds on my PC for an array of integers or doubles. The time is about the same for integers and doubles because they are both stored as variants. A variant takes up 16 bytes when you're running 32 bit whether the variant contains a 4 bytes integer or an 8 bytes double. Why did the conversions in the previous section only take 2.5 seconds on my PC? Only about half as much time. I can only guess that this must be caused by the fact that this was an uninitialized array. And for an uninitialized array the conversions on function entry seems to be much faster. Conversions of an array of strings takes longer time. The variants which contains pointers to the strings has to be copied. And the strings (BSTRs) themselves has to be copied. That's the reason why the number of strings is limited to about 1,000,000. Still a decent number of strings. Although the assembler, C, C++, C# or FreeBasic code is lightning fast, the conversions especially for very large arrays means that the total execution time for the entire function (FillArray in the example in the previous section) will be increased with a few seconds. On the other hand we need the conversions. We don't want the array to be returned as a safearray contained in a variant. We want the array to be returned as a native AutoIt array. Exploiting conversions As I wrote in first section I've been playing with RectToVariant method of the UIAutomation object. In Remarks section in the link you can read this sentence: "The returned VARIANT has a data type of VT_ARRAY | VT_R8." (= VT_ARRAY + VT_R8). But this does not match the internal implementation of an AutoIt array which is VT_ARRAY + VT_VARIANT. Because RectToVariant returns a perfect AutoIt array this must mean that the conversion code also inspects the variant array type and converts it to a VT_ARRAY + VT_VARIANT type if necessary. I've tested that variants of types VT_ARRAY+VT_I4 (integers), VT_ARRAY+VT_R8 (doubles) and VT_ARRAY+VT_BSTR (strings) are properly converted to variants of type VT_ARRAY+VT_VARIANT. Rememeber that a variant of type VT_ARRAY+VT_I4 is a variant which contains a safearray (VT_ARRAY), where the pvData element of the safearray structure points to a memory area which contains a continuous row of integers (VT_I4). What is a continuous row of integers? Well, in AutoIt you create a continuous row of integers with DllStructCreate like this: Local $tIntegers = DllStructCreate( "int[50000]" ) This is a continuous row of 50000 integers. This means that if you are manipulating an array of integers in your assembler, C, C++, C# or FreeBasic code, you don't have to mess around with variant structures containing integers. You can simply use an array of integers. When you've finished the array manipulations you can store the integers as a fairly simple VT_ARRAY+VT_I4 variant (safearray of integers). And then you can leave it to the conversion code on function exit to convert the variant to a VT_ARRAY+VT_VARIANT variant (safearray of variants) which is understandable by AutoIt. And in fact, all these safearray data types are correctly converted to safearrays of variants: $VT_I2, $VT_I4, $VT_R4, $VT_R8, $VT_BSTR, $VT_BOOL, $VT_UI4, $VT_UI8 Example2a/b/c.au3, Example3a/b/c.au3 and Example4a/b/c.au3 demonstrates this technique in three slightly different ways for integers, doubles and strings. These techniques are needed in the assembler, C, C++, C# or FreeBasic code. Note that the examples are based on the final UDF and not the test UDF. See next section. This is Example2a.au3: ;#AutoIt3Wrapper_UseX64=y #include "..\..\..\Includes\AccessingVariables.au3" ; <<<< Final UDF (not test UDF) >>>> #include "..\..\..\Includes\InspectVariable.au3" #include <Array.au3> Opt( "MustDeclareVars", 1 ) Example2() Func Example2() Local $aArray ; Empty string ConsoleWrite( "--- InspectVariable ---" & @CRLF ) InspectVariable( $aArray ) ; $aArray is an empty string AccessVariables01( CreateArray, $aArray ) ConsoleWrite( "--- InspectVariable ---" & @CRLF ) InspectVariable( $aArray ) ; $aArray is an array ConsoleWrite( "--- InspectArray ---" & @CRLF ) InspectArray( $aArray ) _ArrayDisplay( $aArray ) EndFunc Func CreateArray( $pVariant ) ; --- Create and fill structure of integers --- ; Create structure Local $tIntegers = DllStructCreate( "int[50000]" ) Local $pIntegers = DllStructGetPtr( $tIntegers ) ; Fill structure ; Array manipulation For $i = 0 To 50000 - 1 DllStructSetData( $tIntegers, 1, $i, $i + 1 ) Next ; --- Create and fill safearray --- ; Create safearray Local $tSafeArrayBound = DllStructCreate( $tagSAFEARRAYBOUND ) DllStructSetData( $tSafeArrayBound, "cElements", 50000 ) ; Number of elements in array DllStructSetData( $tSafeArrayBound, "lLbound", 0 ) ; Lower bound of array index Local $pSafeArray = SafeArrayCreate( $VT_I4, 1, $tSafeArrayBound ) ; <<<< Not a proper AutoIt safearray >>>> ; This is a safearray of integers and not variants as a usual AutoIt array ; Pointer to data Local $pSafeArrayData SafeArrayAccessData( $pSafeArray, $pSafeArrayData ) ; Create structure from safearray data area Local $tSafeArrayBytes = DllStructCreate( "byte[200000]", $pSafeArrayData ) ; Fill safearray data area with data from $tIntegers DllStructSetData( $tSafeArrayBytes, 1, DllStructGetData( DllStructCreate( "byte[200000]", $pIntegers ), 1 ) ) ; This technique only works with byte's, char's and wchar's SafeArrayUnaccessData( $pSafeArray ) ; --- Set variant to match an array of integers --- ; Set vt element to $VT_ARRAY + $VT_I4 Local $tvt = DllStructCreate( "word", $pVariant ) DllStructSetData( $tvt, 1, $VT_ARRAY + $VT_I4 ) ; <<<< Not a proper AutoIt array >>>> ; This is an array of integers and not variants as a usual AutoIt array ; Set data element to safearray pointer Local $pData = $pVariant + 8 Local $tData = DllStructCreate( "ptr", $pData ) DllStructSetData( $tData, 1, $pSafeArray ) ; <<<< On function exit the safearray contained in a variant is converted to a native AutoIt array >>>> EndFunc This is output in SciTE console. The array is displayed with _ArrayDisplay. --- InspectVariable --- ptr = 0x00D0E698 ($pVariant) vt = 0x0008 (VT_BSTR, basic string) data = --- InspectVariable --- ptr = 0x02B78028 ($pVariant) vt = 0x200C (VT_ARRAY+VT_VARIANT, array of variants, safearray) data = 0x00CAB170 (pointer to safearray) --- InspectArray --- Number of dimensions = 1 Features flags = 0x00000880 ($FADF_VARIANT+$FADF_HAVEVARTYPE, array of variants) Variant type = 0x000C (VT_VARIANT, variant data type) Size of array element (bytes) = 16 (size of the variant structure) Number of locks = 0 Pointer to data = 0x02EF0020 (pvData) Dimension 1: Elements in dimension = 50000 Lower bound of dimension = 0 Avoiding conversions For large arrays conversions may take quite some time. The conversions cannot be avoided, but in some situations they can be limited. Eg. a large array with 10 columns to sort by four columns (like the details view in Windows Explorer can be sorted by name, date, type and size). In this situation four indexes can be used to implement the sorting. And because it's a large array the indexes should be created with compiled code. Instead of converting the large array four times (once for each index), it would be much better to get a pointer to the safearray, and then reuse this pointer for each index. It'll only require one conversion of the large array to get a pointer to the safearray. For this purpose two functions in Includes\AccVarsUtilities.au3 can be used: AccVars_ArrayToSafeArray which creates a pointer to a safearray from a native AutoIt array, and AccVars_SafeArrayToArray which creates a native AutoIt array from a pointer to a safearray. More about these functions i a later section. Example5.au3 shows how long time it takes for the two functions to create a safearray and an array: ;#AutoIt3Wrapper_UseX64=y #include "..\..\..\Includes\AccessingVariables.au3" ; <<<< Final UDF (not test UDF) >>>> #include "..\..\..\Includes\AccVarsUtilities.au3" #include "..\..\..\Includes\ArrayDisplayEx.au3" Opt( "MustDeclareVars", 1 ) Example5() Func Example5() ; --- Array of integers --- ConsoleWrite( "Filling array of 16,777,216 integers (~10 seconds) ..." & @CRLF ) Local $aArray1[2^24] ; 2^24 = 16,777,216, maximum number of elements for an array For $i = 0 To 2^24 - 1 $aArray1[$i] = 1234 Next Local $pSafeArray1 Local $hTimer = TimerInit() AccVars_ArrayToSafeArray( $aArray1, $pSafeArray1 ) ConsoleWrite( "Time for AccVars_ArrayToSafeArray to execute: " & TimerDiff( $hTimer ) & @CRLF ) _ArrayDisplayEx( $aArray1 ) $aArray1 = 0 Local $aArray2 $hTimer = TimerInit() AccVars_SafeArrayToArray( $pSafeArray1, $aArray2 ) ConsoleWrite( "Time for AccVars_SafeArrayToArray to execute: " & TimerDiff( $hTimer ) & @CRLF & @CRLF ) _ArrayDisplayEx( $aArray2 ) $aArray2 = 0 ; --- Array of doubles --- ConsoleWrite( "Filling array of 16,777,216 doubles (~10 seconds) ..." & @CRLF ) Local $aArray3[2^24] ; 2^24 = 16,777,216, maximum number of elements for an array For $i = 0 To 2^24 - 1 $aArray3[$i] = 1234.5678 Next Local $pSafeArray3 $hTimer = TimerInit() AccVars_ArrayToSafeArray( $aArray3, $pSafeArray3 ) ConsoleWrite( "Time for AccVars_ArrayToSafeArray to execute: " & TimerDiff( $hTimer ) & @CRLF ) _ArrayDisplayEx( $aArray3 ) $aArray3 = 0 Local $aArray4 $hTimer = TimerInit() AccVars_SafeArrayToArray( $pSafeArray3, $aArray4 ) ConsoleWrite( "Time for AccVars_SafeArrayToArray to execute: " & TimerDiff( $hTimer ) & @CRLF & @CRLF ) _ArrayDisplayEx( $aArray4 ) $aArray4 = 0 ; --- Array of strings --- ConsoleWrite( "Filling array of 1,048,576 100-chars strings (~5 seconds) ..." & @CRLF ) Local $aArray5[2^20] ; 2^20 = 1,048,576 For $i = 0 To 2^20 - 1 $aArray5[$i] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ; 100 chars Next Local $pSafeArray5 $hTimer = TimerInit() AccVars_ArrayToSafeArray( $aArray5, $pSafeArray5 ) ConsoleWrite( "Time for AccVars_ArrayToSafeArray to execute: " & TimerDiff( $hTimer ) & @CRLF ) _ArrayDisplayEx( $aArray5 ) $aArray5 = 0 Local $aArray6 $hTimer = TimerInit() AccVars_SafeArrayToArray( $pSafeArray5, $aArray6 ) ConsoleWrite( "Time for AccVars_SafeArrayToArray to execute: " & TimerDiff( $hTimer ) & @CRLF ) _ArrayDisplayEx( $aArray6 ) $aArray6 = 0 EndFunc Output in SciTE console: Filling array of 16,777,216 integers (~10 seconds) ... Time for AccVars_ArrayToSafeArray to execute: 4493.62536677101 Time for AccVars_SafeArrayToArray to execute: 1164.59904458766 Filling array of 16,777,216 doubles (~10 seconds) ... Time for AccVars_ArrayToSafeArray to execute: 4549.6914981711 Time for AccVars_SafeArrayToArray to execute: 1159.73609940987 Filling array of 1,048,576 100-chars strings (~5 seconds) ... Time for AccVars_ArrayToSafeArray to execute: 2419.86058615209 Time for AccVars_SafeArrayToArray to execute: 675.048988223156 Note that a consequence of the conversions is that the input safearray for AccVars_SafeArrayToArray is deleted. If you need to use the same safearray several times you must make a copy of the safearray with SafeArrayCopy function in Includes\SafeArray.au3. In the example with fasm code in previous section we got this result: Time for FillArray to fill array: 2388.37594979003 In top of post we got this result for more or less the same code: Applied time to create and fill array (UDF and fasm): 797.855906880413 Three times as fast. This is a consequence of limiting conversions. In a few situations it may be possible to completely avoid conversions. Eg. if the data will be used to fill the rows in a virtual listview. In a virtual listview rows are filled through $LVN_GETDISPINFOW notifications. And for $LVN_GETDISPINFOW notifications it doesn't matter whether the data source is a native AutoIt array or the data structure in a safearray. Final UDF The whole idea of this UDF is to utilize the information we already know: We know that COM objects and methods are working very well in AutoIt. We also know that the only variable type as COM object methods are familiar with is variants (only completely true for IDispatch based objects and objects of Automation compatible types). But how is it possible for an object method to handle variables that are passed to the method as native AutoIt variables, when the only variable type as COM object methods are familiar with is variants? The only explanation is that native AutoIt input parameters must be converted to variants immediately before the method code is executed, and that variant output parameters must be converted to native AutoIt variables immediately after the method code has finished. These conversions must be carried out by internal AutoIt code. The final UDF (Includes\AccessingVariables.au3) makes it possible to pass native AutoIt arrays and simple variables as parameters to a function coded in another language eg. assembler, C, C++, C# or FreeBasic. This is done by executing the function inside an object method and passing the array and variable parameters as variant pointers. Internal AutoIt conversions ensures that AutoIt variables outside the method are properly converted to COM variants inside the method. And the other way around. In the test UDF (Tests\AccessingVariablesTest.au3) only one AutoIt variable is passed to the object method by AccessVariable function. The final UDF contains 30 functions named AccessVariables01 - AccessVariables30 where the number indicates the number of AutoIt variables passed to the object method. Manipulating AutoIt variables in another language (a compiled language) is especially relevant for arrays with a large number of elements, or smaller arrays where complex calculations are performed on the elements. AccessVariablesXY To use the UDF you call one of the AccessVariablesXY functions eg. AccessVariables01. AccessVariables01 is coded in this way: Func AccessVariables01( $hAccVars_Method, ByRef $vVariable01 ) $hAccVars_MethodFunc = $hAccVars_Method $oAccVars_Object.AccVars_VariableToVariant01( $vVariable01 ) EndFunc The first parameter is a function type parameter (the name of an AutoIt function). You must code this function yourself. The function is assigned to the global variable $hAccVars_MethodFunc. The second parameter is an AutoIt variable. Typically an array. This parameter is passed to the AccVars_VariableToVariant01 object method. AccessVariables01 is just a wrapper function to make it easier to call the object method. The description string for the object method looks like this: "AccVars_VariableToVariant01 hresult(variant*);" The AutoIt variable is passed to the method as a variant pointer. And the method is coded in this way: Func AccVars_VariableToVariant01( $pSelf, $pVariant01 ) $hAccVars_MethodFunc( $pVariant01 ) Return 0 ; $S_OK (COM constant) #forceref $pSelf EndFunc The first parameter $pSelf must be a pointer to the object $oAccVars_Object. This is a COM rule. The second parameter is the AutoIt variable you passed to the AccessVariables01 function. But inside AccVars_VariableToVariant01 this is not an AutoIt variable any more. Inside AccVars_VariableToVariant01 it's a pointer to a variant. Inside AccVars_VariableToVariant01 the $hAccVars_MethodFunc is called and the variant pointer is passed as a parameter. $hAccVars_MethodFunc is the function you passed to AccessVariables01. If you passed a native AutoIt array to AccessVariables01, you can extract this array as a pointer to a safearray inside $hAccVars_MethodFunc. And this pointer or a pointer directly to the safearray data area you can pass to a function coded in assembler, C, C++, C# or FreeBasic. When $hAccVars_MethodFunc is finished zero is returned to indicate that everything is OK. Restrictions Because the $vVariableXY parameters in AccessVariablesXY functions are ByRef parameters you cannot pass literal values as parameters. You must store the literal value in a variable and pass the variable. You cannot call an AccessVariablesXY function inside another AccessVariablesXY function. No nested function calls. This also means that you cannot call InspectVariable or InspectArray inside an AccessVariablesXY function. But you can call InspectSafeArray. See InspectVariable section below for info about Inspect-functions. Utility funcs Typically arrays are passed to the object methods. But this does not exclude the need to pass simple variables to the object methods. Eg. the number of rows and columns in the arrays. Simple variables are also passed to object methods as variant pointers. In most cases you probably want to treat simple variables as native AutoIt variables inside object methods and not as variant pointers. AccVars_VariantToVariable (Includes\AccVarsUtilities.au3) converts variant pointers to native AutoIt variables. Arrays are not converted. See "Examples\Demo examples\4) Other demo examples\2) Multiple parameters\Example1.au3". AccVars_VariableToVariant converts native AutoIt variables to variant pointers. Arrays are not converted. See "Examples\Demo examples\4) Other demo examples\6) Using the UDF\Example6.au3" AccVars_ArrayToSafeArray and AccVars_SafeArrayToArray are already mentioned above. AccVars_ArrayToSafeArray creates a pointer to a safearray from a native AutoIt array. AccVars_SafeArrayToArray creates a native AutoIt array from a pointer to a safearray. "Examples\Demo examples\4) Other demo examples\4) ArrayToSafearray\" includes a few examples of AccVars_ArrayToSafeArray. "Examples\Demo examples\4) Other demo examples\5) SafearrayToArray\" includes a few examples of AccVars_SafeArrayToArray. In both folders Example1.au3 shows how everything can be done manually without using the two functions. And Example2.au3 shows how it can be done using the two functions. Note that a consequence of the conversions is that the input safearray for AccVars_SafeArrayToArray is deleted. If you need to use the same safearray several times you must make a copy of the safearray with SafeArrayCopy function in Includes\SafeArray.au3. InspectVariable Includes\InspectVariable.au3 contains three functions: InspectVariable (corresponds to InspectVariableMtd), InspectArray (corresponds to InspectVariableMtd) and InspectSafeArray. The first two are used in many of the test examples. The last is used in the examples for AccVars_ArrayToSafeArray and AccVars_SafeArrayToArray. InspectVariable and InspectArray takes AutoIt variables as input parameters and prints information about the variables in SciTE console after they have been converted to variants. InspectSafeArray prints information about safearrays in SciTE console. Using the UDF Here are six small scripts which shows how to use the UDF. You can use these scripts as templates for your own code. The scripts are saved in "Examples\Demo examples\4) Other demo examples\6) Using the UDF\". The first four scripts is about creating and filling a new array. The array is in all cases a 1D-array with 2^24 (16,777,216) integer elements. In Example1.au3 an AutoIt integer structure is filled with data, the data in the structure is copied into a safearray which is converted to a native AutoIt array: ;#AutoIt3Wrapper_UseX64=y #include "..\..\..\..\Includes\AccVarsUtilities.au3" #include "..\..\..\..\Includes\ArrayDisplayEx.au3" #include "..\..\..\..\Includes\FasmUtils.au3" Opt( "MustDeclareVars", 1 ) Example1() Func Example1() Local $hTimer = TimerInit() ; --- Create and fill structure of integers --- ; Create structure of integers Local $tIntegers = DllStructCreate( "int[" & 2^24 & "]" ) ; 2^24 = 16,777,216 elements Local $pIntegers = DllStructGetPtr( $tIntegers ) ; AutoIt code ;For $i = 0 To 2^24 - 1 ; DllStructSetData( $tIntegers, 1, $i, $i + 1 ) ;Next ; <<<< Execute your assembler, C, C++, C# or FreeBasic code at this point >>>> ; Get fasm code Local $sFasmCode = @AutoItX64 ? "0xB80000000089024883C204FFC0E2F6C3" _ ; Example1-x64.asm : "0x5589E58B4D088B550CB800000000890283C20440E2F85DC20800" ; Example1-x86.asm Local $pFasmCode = FasmGetBinaryString( $sFasmCode, 64 ) If Not $pFasmCode Then Return ConsoleWrite( "$pFasmCode ERR" & @CRLF ) ; Execute fasm code to fill structure DllCallAddress( "int", $pFasmCode, "int", 2^24, "ptr", $pIntegers ) ; --- Create and fill safearray --- ; Create safearray Local $tSafeArrayBound = DllStructCreate( $tagSAFEARRAYBOUND ) DllStructSetData( $tSafeArrayBound, "cElements", 2^24 ) ; Number of elements in array DllStructSetData( $tSafeArrayBound, "lLbound", 0 ) ; Lower bound of array index Local $pSafeArray = SafeArrayCreate( $VT_I4, 1, $tSafeArrayBound ) ; Pointer to data Local $pSafeArrayData SafeArrayAccessData( $pSafeArray, $pSafeArrayData ) ; Create structure from safearray data area Local $tSafeArrayBytes = DllStructCreate( "byte[" & 4 * 2^24 & "]", $pSafeArrayData ) ; Fill safearray data area with data from $tIntegers DllStructSetData( $tSafeArrayBytes, 1, DllStructGetData( DllStructCreate( "byte[" & 4 * 2^24 & "]", $pIntegers ), 1 ) ) ; This technique only works with byte's, char's and wchar's SafeArrayUnaccessData( $pSafeArray ) $tIntegers = 0 ; --- Convert safearray to native AutoIt array --- Local $aArray AccVars_SafeArrayToArray( $pSafeArray, $aArray ) ConsoleWrite( "Time to fill array: " & TimerDiff( $hTimer ) & @CRLF ) _ArrayDisplayEx( $aArray ) $aArray = 0 EndFunc ; Time to fill array: 939.174260660843 This example is simple because you're not dealing with variants or safearrays at all in your assembler, C, C++, C# or FreeBasic code. In Example2.au3 the data area of a safearray is directly filled with integers and the safearray is converted to a native AutoIt array: ;#AutoIt3Wrapper_UseX64=y #include "..\..\..\..\Includes\AccVarsUtilities.au3" #include "..\..\..\..\Includes\ArrayDisplayEx.au3" #include "..\..\..\..\Includes\FasmUtils.au3" Opt( "MustDeclareVars", 1 ) Example2() Func Example2() Local $hTimer = TimerInit() ; --- Create and fill safearray --- ; Create safearray Local $tSafeArrayBound = DllStructCreate( $tagSAFEARRAYBOUND ) DllStructSetData( $tSafeArrayBound, "cElements", 2^24 ) ; Number of elements in array DllStructSetData( $tSafeArrayBound, "lLbound", 0 ) ; Lower bound of array index Local $pSafeArray = SafeArrayCreate( $VT_I4, 1, $tSafeArrayBound ) ; Pointer to data Local $pSafeArrayData SafeArrayAccessData( $pSafeArray, $pSafeArrayData ) ; AutoIt code ;For $i = 0 To 2^24 - 1 ; DllStructSetData( $tSafeArrayData, 1, $i, $i + 1 ) ;Next ; <<<< Execute your assembler, C, C++, C# or FreeBasic code at this point >>>> ; Get fasm code Local $sFasmCode = @AutoItX64 ? "0xB80000000089024883C204FFC0E2F6C3" _ ; Example1-x64.asm : "0x5589E58B4D088B550CB800000000890283C20440E2F85DC20800" ; Example1-x86.asm Local $pFasmCode = FasmGetBinaryString( $sFasmCode, 64 ) If Not $pFasmCode Then Exit ConsoleWrite( "$pFasmCode ERR" & @CRLF ) ; Execute fasm code to fill safearray DllCallAddress( "int", $pFasmCode, "int", 2^24, "ptr", $pSafeArrayData ) SafeArrayUnaccessData( $pSafeArray ) ; --- Convert safearray to native AutoIt array --- Local $aArray AccVars_SafeArrayToArray( $pSafeArray, $aArray ) ConsoleWrite( "Time to fill array: " & TimerDiff( $hTimer ) & @CRLF ) _ArrayDisplayEx( $aArray ) $aArray = 0 EndFunc ; Time to fill array: 805.347826773543 Example2 is more efficient than Example1 because you're avoiding the integer structure. The conversion in Example3.au3 is not performed with AccVars_SafeArrayToArray but with your own SafeArrayToArray method function which is executed through AccessVariables02: ;#AutoIt3Wrapper_UseX64=y #include "..\..\..\..\Includes\AccVarsUtilities.au3" #include "..\..\..\..\Includes\ArrayDisplayEx.au3" #include "..\..\..\..\Includes\FasmUtils.au3" Opt( "MustDeclareVars", 1 ) Example3() Func Example3() Local $hTimer = TimerInit() ; --- Create and fill safearray --- ; Create safearray Local $tSafeArrayBound = DllStructCreate( $tagSAFEARRAYBOUND ) DllStructSetData( $tSafeArrayBound, "cElements", 2^24 ) ; Number of elements in array DllStructSetData( $tSafeArrayBound, "lLbound", 0 ) ; Lower bound of array index Local $pSafeArray = SafeArrayCreate( $VT_I4, 1, $tSafeArrayBound ) ; Pointer to data Local $pSafeArrayData SafeArrayAccessData( $pSafeArray, $pSafeArrayData ) ; AutoIt code ;For $i = 0 To 2^24 - 1 ; DllStructSetData( $tSafeArrayData, 1, $i, $i + 1 ) ;Next ; <<<< Execute your assembler, C, C++, C# or FreeBasic code at this point >>>> ; Get fasm code Local $sFasmCode = @AutoItX64 ? "0xB80000000089024883C204FFC0E2F6C3" _ ; Example1-x64.asm : "0x5589E58B4D088B550CB800000000890283C20440E2F85DC20800" ; Example1-x86.asm Local $pFasmCode = FasmGetBinaryString( $sFasmCode, 64 ) If Not $pFasmCode Then Exit ConsoleWrite( "$pFasmCode ERR" & @CRLF ) ; Execute fasm code to fill safearray DllCallAddress( "int", $pFasmCode, "int", 2^24, "ptr", $pSafeArrayData ) SafeArrayUnaccessData( $pSafeArray ) ; --- Convert safearray to native AutoIt array --- Local $aArray AccessVariables02( SafeArrayToArray, $pSafeArray, $aArray ) ConsoleWrite( "Time to fill array: " & TimerDiff( $hTimer ) & @CRLF ) _ArrayDisplayEx( $aArray ) $aArray = 0 EndFunc Func SafeArrayToArray( $pSafeArray, $pArray ) ; --- Set $pArray to match an AutoIt array --- ; Set vt element to $VT_ARRAY + $VT_VARIANT DllStructSetData( DllStructCreate( "word", $pArray ), 1, $VT_ARRAY + $VT_VARIANT ) ; Set data element to safearray pointer DllStructSetData( DllStructCreate( "ptr", $pArray + 8 ), 1, AccVars_VariantToVariable( $pSafeArray ) ) ; <<<< On function exit $pArray (safearray contained in a variant) is converted to an AutoIt array >>>> EndFunc ; Time to fill array: 800.813455228795 Example3 is a more general example than Example2. Creation of the safearray is moved from AutoIt code to your assembler, C, C++, C# or FreeBasic code in Example4.au3: ;#AutoIt3Wrapper_UseX64=y #include "..\..\..\..\Includes\AccessingVariables.au3" #include "..\..\..\..\Includes\ArrayDisplayEx.au3" #include "..\..\..\..\Includes\FasmUtils.au3" Opt( "MustDeclareVars", 1 ) Example4() Func Example4() ; --- Create and fill array --- Local $aArray Local $hTimer = TimerInit() AccessVariables01( CreateArray, $aArray ) ConsoleWrite( "Time to fill array: " & TimerDiff( $hTimer ) & @CRLF ) _ArrayDisplayEx( $aArray ) $aArray = 0 EndFunc Func CreateArray( $pArray ) ; --- Create and fill safearray --- ; <<<< Execute your assembler, C, C++, C# or FreeBasic code at this point >>>> ; Create safearray Local $tSafeArrayBound = DllStructCreate( $tagSAFEARRAYBOUND ) DllStructSetData( $tSafeArrayBound, "cElements", 2^24 ) ; Number of elements in array DllStructSetData( $tSafeArrayBound, "lLbound", 0 ) ; Lower bound of array index Local $pSafeArray = SafeArrayCreate( $VT_I4, 1, $tSafeArrayBound ) ; Pointer to data Local $pSafeArrayData SafeArrayAccessData( $pSafeArray, $pSafeArrayData ) ; AutoIt code ;For $i = 0 To 2^24 - 1 ; DllStructSetData( $tSafeArrayData, 1, $i, $i + 1 ) ;Next ; Get fasm code Local $sFasmCode = @AutoItX64 ? "0xB80000000089024883C204FFC0E2F6C3" _ ; Example1-x64.asm : "0x5589E58B4D088B550CB800000000890283C20440E2F85DC20800" ; Example1-x86.asm Local $pFasmCode = FasmGetBinaryString( $sFasmCode, 64 ) If Not $pFasmCode Then Exit ConsoleWrite( "$pFasmCode ERR" & @CRLF ) ; Execute fasm code to fill safearray DllCallAddress( "int", $pFasmCode, "int", 2^24, "ptr", $pSafeArrayData ) SafeArrayUnaccessData( $pSafeArray ) ; --- Set $pArray to match an AutoIt array --- ; Set vt element to $VT_ARRAY + $VT_VARIANT DllStructSetData( DllStructCreate( "word", $pArray ), 1, $VT_ARRAY + $VT_VARIANT ) ; Set data element to safearray pointer DllStructSetData( DllStructCreate( "ptr", $pArray + 8 ), 1, $pSafeArray ) ; <<<< On function exit $pArray (safearray contained in a variant) is converted to an AutoIt array >>>> EndFunc ; Time to fill array: 799.20854202792 If you code in assembler it's more advantageous to create the safearray in AutoIt code. The last two scripts is about manipulating an existing array. In both scripts a 1D-array with 2^23 (8,388,608) random integers is searched to find the minimum and maximum value. In Example5.au3 AccVars_ArrayToSafeArray is used to convert the AutoIt array to a safearray: ;#AutoIt3Wrapper_UseX64=y #include "..\..\..\..\Includes\AccVarsUtilities.au3" ;#include "..\..\..\..\Includes\InspectVariable.au3" #include "..\..\..\..\Includes\ArrayDisplayEx.au3" #include "..\..\..\..\Includes\FasmUtils.au3" Opt( "MustDeclareVars", 1 ) Example5() Func Example5() ; --- Create test array of random integers --- ConsoleWrite( "Create test array (~10 seconds) ..." & @CRLF ) Local $aArray[2^23] ; 2^23 = 8,388,608 For $i = 0 To 2^23 - 1 $aArray[$i] = Random( 0, 2^31-1, 1 ) Next _ArrayDisplayEx( $aArray ) ; --- Convert native AutoIt array to safearray --- Local $hTimer = TimerInit() Local $pSafeArray AccVars_ArrayToSafeArray( $aArray, $pSafeArray ) ;InspectSafeArray( $pSafeArray ) ; Pointer to data Local $pSafeArrayData SafeArrayAccessData( $pSafeArray, $pSafeArrayData ) ; --- Test safearray for min/max values --- ; AutoIt code ;Local $iMin1 = 2^31-1, $iMax1 = 0 ;For $i = 0 To 2^23 - 1 ; If $aArray[$i] < $iMin1 Then $iMin1 = $aArray[$i] ; If $aArray[$i] > $iMax1 Then $iMax1 = $aArray[$i] ;Next ; <<<< Execute your assembler, C, C++, C# or FreeBasic code at this point >>>> ; $iMin, $iMax storage for fasm code Local $tMinMax = DllStructCreate( "int iMin;int iMax" ) DllStructSetData( $tMinMax, "iMin", 2^31-1 ) DllStructSetData( $tMinMax, "iMax", 0 ) Local $pMinMax = DllStructGetPtr( $tMinMax ) ; iMin = $pMinMax, iMax = $pMinMax + 4 (int = 4 bytes) ; Get fasm code Static $sFasmCode = @AutoItX64 ? "0x4D8B4804418B003B420876038B4208443B4A087304448B4A084883C218E2E841890045894804C3" _ ; Example5-x64.asm : "0x5589E58B4D088B550C8B45108B58048B003B420876038B42083B5A0873038B5A0883C210E2EB8B55108902895A045DC20C00" ; Example5-x86.asm Static $pFasmCode = FasmGetBinaryString( $sFasmCode, 64 ) If Not $pFasmCode Then Exit ConsoleWrite( "$pFasmCode ERR" & @CRLF ) ; Execute fasm code DllCallAddress( "int", $pFasmCode, "int", 2^23, "ptr", $pSafeArrayData, "ptr", $pMinMax ) ConsoleWrite( "$iMin, $iMax = " & DllStructGetData( $tMinMax, "iMin" ) & ", " & DllStructGetData( $tMinMax, "iMax" ) & @CRLF ) ConsoleWrite( "Time to test array: " & TimerDiff( $hTimer ) & @CRLF ) SafeArrayDestroy( $pSafeArray ) $aArray = 0 EndFunc ; $iMin, $iMax = 262, 2147483599 ; Time to test array: 2293.62874670214 In Example6.au3 the conversion is done in your own TestArray method function which is executed through AccessVariables03: ;#AutoIt3Wrapper_UseX64=y #include "..\..\..\..\Includes\AccVarsUtilities.au3" #include "..\..\..\..\Includes\ArrayDisplayEx.au3" #include "..\..\..\..\Includes\FasmUtils.au3" Opt( "MustDeclareVars", 1 ) Example6() Func Example6() ; --- Create test array of random integers --- ConsoleWrite( "Create test array (~10 seconds) ..." & @CRLF ) Local $aArray[2^23] ; 2^23 = 8,388,608 For $i = 0 To 2^23 - 1 $aArray[$i] = Random( 0, 2^31-1, 1 ) Next _ArrayDisplayEx( $aArray ) ; --- Test array for min/max values --- ; AutoIt code ;Local $iMin1 = 2^31-1, $iMax1 = 0 ;For $i = 0 To 2^23 - 1 ; If $aArray[$i] < $iMin1 Then $iMin1 = $aArray[$i] ; If $aArray[$i] > $iMax1 Then $iMax1 = $aArray[$i] ;Next Local $hTimer = TimerInit() Local $iMin = 2^31-1, $iMax = 0 AccessVariables03( TestArray, $aArray, $iMin, $iMax ) ConsoleWrite( "$iMin, $iMax = " & $iMin & ", " & $iMax & @CRLF ) ConsoleWrite( "Time to test array: " & TimerDiff( $hTimer ) & @CRLF ) $aArray = 0 EndFunc Func TestArray( $pvArray, $pvMin, $pvMax ) ; <<<< On function entry $aArray is converted to $pvArray (safearray contained in a variant) >>>> ; Pointer to safearray Local $pData = $pvArray + 8 Local $tData = DllStructCreate( "ptr", $pData ) Local $pSafeArray = DllStructGetData( $tData, 1 ) ; Pointer to data Local $pSafeArrayData SafeArrayAccessData( $pSafeArray, $pSafeArrayData ) ; <<<< Execute your assembler, C, C++, C# or FreeBasic code at this point >>>> ; $iMin, $iMax storage for fasm code Local $tMinMax = DllStructCreate( "int iMin;int iMax" ) DllStructSetData( $tMinMax, "iMin", AccVars_VariantToVariable( $pvMin ) ) DllStructSetData( $tMinMax, "iMax", AccVars_VariantToVariable( $pvMax ) ) Local $pMinMax = DllStructGetPtr( $tMinMax ) ; iMin = $pMinMax, iMax = $pMinMax + 4 (int = 4 bytes) ; Get fasm code Static $sFasmCode = @AutoItX64 ? "0x4D8B4804418B003B420876038B4208443B4A087304448B4A084883C218E2E841890045894804C3" _ ; Example5-x64.asm : "0x5589E58B4D088B550C8B45108B58048B003B420876038B42083B5A0873038B5A0883C210E2EB8B55108902895A045DC20C00" ; Example5-x86.asm Static $pFasmCode = FasmGetBinaryString( $sFasmCode, 64 ) If Not $pFasmCode Then Exit ConsoleWrite( "$pFasmCode ERR" & @CRLF ) ; Execute fasm code DllCallAddress( "int", $pFasmCode, "int", 2^23, "ptr", $pSafeArrayData, "ptr", $pMinMax ) ; Get $iMin, $iMax AccVars_VariableToVariant( DllStructGetData( $tMinMax, "iMin" ), $pvMin ) AccVars_VariableToVariant( DllStructGetData( $tMinMax, "iMax" ), $pvMax ) SafeArrayUnaccessData( $pSafeArray ) EndFunc ; $iMin, $iMax = 39, 2147483610 ; Time to test array: 2182.54509368366 Examples There are two obvious uses for this: To create and fill a new array. And to manipulate one or more existing arrays. Demo examples "Examples\Demo examples\" contains a few simple demonstration examples. 1) Create and fill new array There are already examples above where a 1D-array is filled with integers. As a demonstration example of creating and filling out an array, a little more complex 2D-array is filled with integers. Example2.au3 is an optimized version of Example1.au3. See post 6. 2) Manipulate existing array As a demonstration example of manipulating a single existing array, minimum and maximum values are determined in a 1D-array of random integers. This is the same as Example5 and Example6 above. See post 6. 3) Concatenate 1D-arrays As a demonstration example of manipulating several existing arrays 2, 8 and 16 1D-arrays of integers with 2^20 (1,048,576) rows are concatenated into a 2D-array with 2, 8 and 16 columns. See post 6. In all three demonstration examples flat assembler (fasm) is used as the fast language to manipulate the arrays. Note that in the three examples the pure AutoIt code is doing relatively well compared to the fasm code. The reason is that the code in the array loops is very simple. For more complex code the AutoIt code will not do so well. Assembler code flat assembler (fasm) is available as a DLL-file. This means that all you need to create fasm code is this DLL and the DllCall command. DllCall is a native AutoIt command. The DLL-file is a 32 bit DLL, but it can generate both 32 and 64 bit fasm code. Furthermore, the assembled code (the executable machine code) is very compact. None of the example programs are larger than 64 bytes. There are several threads in these forums regarding fasm and development of fasm code. And there are threads in the German forums regarding fasm. For the example programs included here I'm just using the DLL-file, DllCall and a few AutoIt functions to make things easier. Nothing of this is included in the zip. Other demo examples These are small examples I used while I developed and tested the UDF. The examples are stored in "Examples\Demo examples\4) Other demo examples\". Create and fill array\ contains the the same examples as "Tests\Examples\3) Internal conversions\". Multiple parameters\ tests all 30 AccessVariablesXY functions. The functions are tested with simple variables where some variables are added and the result is stored in another variable. Example1.au3. Inside the AccessVariablesXY functions the variables are true variants. This is demonstrated by adding the variables with VarAdd API function. Example2.au3. Safearray dimensions\ shows how to handle safearrays of 1, 2 and 3 dimensions. ArrayToSafearray\ and SafearrayToArray\ is about the AccVars_ArrayToSafeArray and AccVars_SafeArrayToArray utility functions. Using the UDF\ contains the six examples in the previous section. Real examples The examples of fasm code that I've used for tests and demonstrations are almost too small to be realistic examples. But so far I've not finalized any more realistic examples. I'll add some examples when they are completed. Zip file At the top level the zip contains the following folders and files: Examples\ - Examples main section Includes\ - Final UDF main section Tests\ - The first four sections Example.au3 - Example in top of post Example-x64.asm - 64 bit fasm code Example-x86.asm - 32 bit fasm code You need AutoIt 3.3.10 or later. Tested on Windows 10/7 32/64 bit and Windows XP 32 bit. If you have less than 4GB of RAM in your PC, you should reduce the number of array rows by a factor of four (change 2^24, 2^23, 2^20 to 2^22, 2^21, 2^18 in .au3-files) in examples with fasm code. Comments are welcome. Let me know if there are any issues. AccessingVariables.7z
    1 point
  5. @mLipok asked me to come up with an AutoIt example for this. So here's what I came up with, including an added bonus. #include <Array.au3> Global $oMyError = ObjEvent('AutoIt.Error', '_ErrFunc') Global $sLocale = 'en' Global $sCountry = 'US' Global $sWord = InputBox("Spell Checker", "File to check (empty for end)?") While $sWord <> "" Global $vSpell = _OOo_SpellChecker($sWord, $sLocale, $sCountry) If $vSpell Then MsgBox(0, "Spell Checker", $sWord & " is valid") Else If MsgBox(4, "Spell Checker", $sWord & " is NOT valid. Would you like to see alternatives?") = 6 Then Global $aAlternatives = _OOo_SpellChecker($sWord, $sLocale, $sCountry, True) _ArrayDisplay($aAlternatives, "Spell Checker") EndIf EndIf $sWord = InputBox("Spell Checker", "File to check (empty for end)?") WEnd ; #FUNCTION# ==================================================================================================================== ; Name ..........: _OOo_SpellChecker ; Description ...: Checks a single word with the OpenOffice/LibreOffice spell checker to see if it is spelled correctly in a ; given locale. ; Syntax ........: _OOo_SpellChecker($sWord[, $sLocale = 'en'[, $sCountry = 'US'[, $bShowAlternatives = False]]]) ; Parameters ....: $sWord - a string value. ; $sLocale - [optional] a string value. Default is 'en'. ; $sCountry - [optional] a string value. Default is 'US'. ; $bShowAlternatives - [optional] a boolean value. Default is False. ; Return values .: On Success - Returns True if the word is spelled correctly using the specified language, False ; otherwise. If word is not spelled correctly and $bShowAlternatives is set to True, ; an array of suggestions is returned. ; On Failure - Returns 0 and sets @error and @extended: ; | @error = 0 - Success (No error) ; | 1 - General error ; | 2 - Invalid type ; | 3 - Invalid value ; | 4 - No match found ; | @extended = number of offending parameter ; Author ........: GMK ; Modified ......: ; Remarks .......: ; Related .......: ; Link ..........: https://www.openoffice.org/api/docs/common/ref/com/sun/star/linguistic2/XSpellChecker.html ; https://www.openoffice.org/api/docs/common/ref/com/sun/star/linguistic2/XSpellAlternatives.html ; http://www.loc.gov/standards/iso639-2/php/code_list.php ; https://www.iso.org/obp/ui/#search ; Example .......: Yes ; =============================================================================================================================== Func _OOo_SpellChecker($sWord, $sLocale = 'en', $sCountry = 'US', $bShowAlternatives = False) Local Enum $eErr_Success, _ $eErr_GeneralError, _ $eErr_InvalidType, _ $eErr_InvalidValue, _ $eErr_NoMatch If Not IsString($sWord) Then Return SetError($eErr_InvalidType, 1, 0) If StringRegExp($sWord, '\d|\s') Then Return SetError($eErr_InvalidValue, 1, 0) If Not IsString($sLocale) Then Return SetError($eErr_InvalidType, 2, 0) If StringLen($sLocale) <> 2 Then Return SetError($eErr_InvalidValue, 2, 0) If Not IsString($sCountry) Then Return SetError($eErr_InvalidType, 3, 0) If StringLen($sCountry) <> 2 Then Return SetError($eErr_InvalidValue, 3, 0) Local $oSM = ObjCreate('com.sun.star.ServiceManager') If Not IsObj($oSM) Then Return SetError($eErr_GeneralError, 10, 0) Local $oLocale = $oSM.Bridge_GetStruct('com.sun.star.lang.Locale') If Not IsObj($oLocale) Then Return SetError($eErr_GeneralError, 11, 0) $oLocale.Language = $sLocale $oLocale.Country = $sCountry Local $oLinguService = $oSM.createInstance('com.sun.star.linguistic2.LinguServiceManager') If Not IsObj($oLinguService) Then Return SetError($eErr_GeneralError, 12, 0) Local $oSpellChecker = $oLinguService.getSpellChecker If Not IsObj($oSpellChecker) Then Return SetError($eErr_GeneralError, 13, 0) If Not $oSpellChecker.hasLocale($oLocale) Then Return SetError($eErr_NoMatch, 2, 0) Local $oPropertyValue = $oSM.Bridge_GetStruct('com.sun.star.beans.PropertyValue') If Not IsObj($oPropertyValue) Then Return SetError($eErr_GeneralError, 14, 0) Local $aPropertyValue[1] = [$oPropertyValue] Local $nRandom = Random(0, 0.5) Local $bReturn = $oSpellChecker.isValid($sWord, $nRandom, $aPropertyValue) If @error Then Return SetError($eErr_GeneralError, 15, 0) If Not $bReturn And $bShowAlternatives Then Local $oSpell = $oSpellChecker.spell($sWord, $nRandom, $aPropertyValue) If Not IsObj($oSpell) Then Return SetError($eErr_GeneralError, 16, 0) Local $aReturn = $oSpell.getAlternatives() Local $iAlternatives = UBound($aReturn) ReDim $aReturn[$iAlternatives + 1] $iAlternatives += 1 For $i = $iAlternatives - 1 To 1 Step -1 $aReturn[$i] = $aReturn[$i - 1] Next $aReturn[0] = $oSpell.getAlternativesCount() If @error Then Return SetError($eErr_GeneralError, 17, 0) Return SetError($eErr_Success, 0, $aReturn) EndIf Return SetError($eErr_Success, 0, $bReturn) EndFunc Func _ErrFunc($oError) ConsoleWrite(@ScriptName & ' (' & $oError.scriptline & ') : ==> COM Error intercepted !' & @CRLF & _ @TAB & 'err.number is: ' & @TAB & @TAB & '0x' & Hex($oError.number) & @CRLF & _ @TAB & 'err.windescription:' & @TAB & $oError.windescription & @CRLF & _ @TAB & 'err.description is: ' & @TAB & $oError.description & @CRLF & _ @TAB & 'err.source is: ' & @TAB & @TAB & $oError.source & @CRLF & _ @TAB & 'err.helpfile is: ' & @TAB & $oError.helpfile & @CRLF & _ @TAB & 'err.helpcontext is: ' & @TAB & $oError.helpcontext & @CRLF & _ @TAB & 'err.lastdllerror is: ' & @TAB & $oError.lastdllerror & @CRLF & _ @TAB & 'err.scriptline is: ' & @TAB & $oError.scriptline & @CRLF & _ @TAB & 'err.retcode is: ' & @TAB & '0x' & Hex($oError.retcode) & @CRLF & @CRLF) EndFunc ;==>_ErrFunc
    1 point
  6. mikell

    compare two arrays

    Another funny - and faster - way #include <Array.au3> Local $Array1[5] = [1,2,3,4,5] ; Array mit den Werten für die Suche Local $Array2[5] = [7,4,5,6,3] ; Array, dass durchsucht wird _ArrayDisplay($Array2) Local $sd2 = ObjCreate("Scripting.Dictionary") For $i In $Array2 $sd2.Item($i) Next For $i In $Array1 $sd2.Remove($i) Next $Array2 = $sd2.Keys() _ArrayDisplay($Array2)
    1 point
  7. NorhanFoda

    FEN, SAN and PGN

    Thank you! I am already have open source chess programs and trying to locate the code and keep going, you've done a great work
    1 point
  8. Hobbyist, This works with the 8 posted files and the previously posted corrupted one. Why didn't you post all 10 files ? #include <Array.au3> #include <File.au3> $a = _FileListToArray (@scriptdir & "\GOODFILE", "*.CSV", $FLTA_FILES, true) _ArrayDisplay($a,"files") For $i = 1 to $a[0] $f = FileRead($a[$i]) $f = StringReplace($f, '"', "") $f = StringRegExpReplace($f, '(\N+\R\N+)\K\R', "") $f = StringRegExpReplace($f, ',,(?=,|\R)', "") $array = _CSVSplit($f) _ArrayDisplay($array, $i & " - " & $a[$i]) Next
    1 point
  9. water

    Convert VBS to AU3

    Great
    1 point
  10. Maybe not but maybe. If a string will become a literal part of a pattern, then care should indeed be taken so that it is interpreted literally. One way is escaping everything (as already proposed), escaping only PCRE special chars (already proposed too), include it inside \Q ... \E (already proposed as well) BUT the string then has to be filtered and "passivated" if it contains the literal \E itself. So replacing occurences of \E by \\E and including the thing inside \Q ... \E covers all bases ... in simple cases. Yet there is a catch: this last possibility can't be used if the surrounding part of the final pattern may contain \Q ... \E itself because \Q ... \E don't nest! So you have to be aware of the use context and cautious if you don't have a clue about nor control over the content of the overall pattern.
    1 point
  11. water

    Convert VBS to AU3

    Shouldn't be too hard: Local $oLocation = ObjCreate("WbemScripting.SWbemLocator") Local $oServices = $oLocation.ConnectServer(Default, "Root\CIMV2") ; Not sure about the Default here Local $SaveClass = $oServices.Get $SaveClass.Path_.Class = "test_USER_REGKEY" $SaveClass.Properties_.add("Caption", 8) $SaveClass.Properties_.add("Name", 8) $SaveClass.Properties_.add("Vendor", 8) $SaveClass.Properties_.add("Version", 8) $SaveClass.Properties_("Name").Qualifiers_.add("key", false) $SaveClass.Put_ $SaveClass = ObjGet("winmgmts:Root\CIMV2:test_USER_REGKEY").SpawnInstance_ $SaveClass.Caption = "Test save key" $SaveClass.Name = "Test for save key" $SaveClass.Vendor = "TESTER" $SaveClass.Version = "1.1" $SaveClass.Put_
    1 point
  12. Here is a 5 minute try, to give you some ideas (500 lines less, it's worth a try) #cs ---------------------------------------------------------------------------- AutoIt Version: 3.3.12.0 Date: 06/10/16 Script Function: Loaner Laptop Log #ce ---------------------------------------------------------------------------- #include <File.au3> #include <ButtonConstants.au3> #include <ComboConstants.au3> #include <EditConstants.au3> #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3> #include <String.au3> ;GUI #Region ### START Koda GUI section ### Form=c:\users\athenos\desktop\form1.kxf $Form1_1 = GUICreate("Loaner Laptop Log", 361, 210, Default, Default) $List = GUICtrlCreateCombo("", 128, 16, 90, 25, BitOR($CBS_DROPDOWN,$CBS_AUTOHSCROLL)) GUICtrlSetData(-1, "|LAPTOP 1|LAPTOP 2|LAPTOP 3|LAPTOP 4|LAPTOP 5|LAPTOP 6|LAPTOP 7|LAPTOP 8|LAPTOP 9|LAPTOP 10|LAPTOP 11|LAPTOP 12") $Label1 = GUICtrlCreateLabel("Machine:", 64, 21, 48, 17) $Label2 = GUICtrlCreateLabel("Customer:", 64, 61, 51, 17) $Username = GUICtrlCreateInput("", 128, 56, 137, 21) $Button1 = GUICtrlCreateButton("Machine In", 36, 149, 153, 46) $Button2 = GUICtrlCreateButton("Machine Out", 36, 96, 153, 46) $Button3 = GUICtrlCreateButton("Audit", 216, 149, 105, 46) $Button4 = GUICtrlCreateButton("Check on Status", 216, 96, 105, 46) $Button5 = GUICtrlCreateButton("LAT?", 232, 15, 41, 25) $Button6 = GUICtrlCreateButton("Update", 280, 15, 41, 25) GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### ;--------------------------------------------------------------------------------------------------------------------------------------- While 1 $Msg = GUIGetMsg() Select Case $Msg = $GUI_EVENT_CLOSE Exit ;--------------------------------------------------------------------------------------- Case $Msg = $Button1 ;--------------------------------------------------------------------------------------- ;Open the file for writing $file = FileOpen("C:\TEST.txt", 1) ;Process after button press If GUICtrlRead($List) = "" Then MsgBox (16,"ERROR", "Please select a loaner laptop machine number") Else stateIn(GUICtrlRead($List)) EndIf ;---------------------------------------------------------------------------------------- Case $MSg = $Button2 ;---------------------------------------------------------------------------------------- ;Open the file for writing $file = FileOpen("C:\TEST.txt", 1) ;Process after button press If GUICtrlRead($List) = "" Then MsgBox (16,"ERROR", "Please select a loaner laptop machine number") Else stateOut(GUICtrlRead($List)) EndIf ;---------------------------------------------------------------------------------------- Case $MSg = $Button3 ;---------------------------------------------------------------------------------------- ;Open the file for writing $file = FileOpen("C:\TEST.txt", 1) ;Process after button press Global $aMachines, $sMachine = GUICtrlRead($List) _FileReadToArray('C:\TEST.txt', $aMachines) $sFound = _SearchLastState($sMachine) MsgBox($MB_ICONINFORMATION, "Last Status for "&$sMachine&" ", $sFound) ;----------------------------------------------------------------------------------------- Case $MSg = $Button4 ;----------------------------------------------------------------------------------------- ;Open the file for writing $file = FileOpen("C:\TEST.txt", 1) ;Process after button press $sFile = "C:\TEST.txt" Local $sText = FileRead($sFile) $sMachineSearched = GUICtrlRead($List) $sFound = StringRegExpReplace($sText, '(?is).*' & $sMachineSearched & '\h\N*\b(In|Out)\b.*', "$1") Msgbox(0,"", $sMachineSearched & " is " & $sFound) ;----------------------------------------------------------------------------------------- Case $MSg = $Button5 ;----------------------------------------------------------------------------------------- ;Open the file for writing $file = FileOpen("C:\TEST2.txt", 1) ;Process after button press Global $aLATs, $sLAT = GUICtrlRead($List) _FileReadToArray('C:\TEST2.txt', $aLATs) $sFound = _SearchLastLap($sLAT) MsgBox($MB_ICONINFORMATION, "Machine Number for "&$sLAT&" ", $sFound) ;----------------------------------------------------------------------------------------- Case $MSg = $Button6 ;----------------------------------------------------------------------------------------- ;2nd GUI pop-up for updating LAT number when a machine changes ;----------------------------------------------------------------------------------------- #Region ### START Koda GUI section ### Form=C:\Users\Athenos\Desktop\Prod\Link Program.kxf $Form1_1 = GUICreate("Update LAT number", 267, 141, Default, Default) $List = GUICtrlCreateCombo("", 160, 16, 89, 25, BitOR($CBS_DROPDOWN,$CBS_AUTOHSCROLL)) GUICtrlSetData(-1, "|LAPTOP 1|LAPTOP 2|LAPTOP 3|LAPTOP 4|LAPTOP 5|LAPTOP 6|LAPTOP 7|LAPTOP 8|LAPTOP 9|LAPTOP 10|LAPTOP 11|LAPTOP 12") $Label1 = GUICtrlCreateLabel("Confirm machine to change:", 16, 21, 136, 17) $Label2 = GUICtrlCreateLabel("Enter new laptop number:", 16, 61, 125, 17) $UserInput = GUICtrlCreateInput("", 160, 56, 89, 21) $Button9 = GUICtrlCreateButton("Submit Change", 80, 92, 107, 33) GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### While 1 $Msg = GUIGetMsg() Select Case $Msg = $GUI_EVENT_CLOSE Exit Case $Msg = $Button9 $file = FileOpen("C:\TEST2.txt", 1) ;Process after button press If GUICtrlRead($List) = "" Then MsgBox (16,"ERROR", "Please select a loaner laptop machine number") Else stateEdit(GUICtrlRead($List)) EndIf EndSelect WEnd Exit EndSelect WEnd ;------------------------------------------------------------------------------------------------------------------------------ ;Functions ;------------------------------------------------------------------------------------------------------------------------------ Func _SearchLastState($sMachine) For $i = $aMachines[0] To 1 Step -1 If StringInStr($aMachines[$i], $sMachine & ' ') Then Return $aMachines[$i] ;If StringInStr($aMachines[$i], $sMachine) Then Return $aMachines[$i] Next EndFunc Func _SearchLastLap($sLAT) For $i = $aLATs[0] To 1 Step -1 If StringInStr($aLATs[$i], $sLAT) Then Return $aLATs[$i] Next EndFunc ;------------------------------------------------------------------------------------------------------------------------------ ;Processing Check In of Machines ;------------------------------------------------------------------------------------------------------------------------------ Func stateIn($machine) If $file = -1 Then MsgBox(0, "Error", "Unable to open file.") Else If GuiCtrlRead($Username) = "" Then MsgBox (16,"ERROR", "Please enter the name of the person picking up or dropping off") Else FileWrite($file, $machine & " checked IN by " & GUICtrlRead($Username) & " on " & @mon & "/" & @mday & "/" & @year & " at " & @hour & ":" & @min & ". Entry logged by " & @UserName & "." & @CRLF) FileClose($file) MsgBox (64,"Processed", "Record Submitted") Exit EndIF EndIf EndFunc ;------------------------------------------------------------------------------------------------------------------------------ ;Processing Check Out of Machines ;------------------------------------------------------------------------------------------------------------------------------ Func stateOut($machine) If $file = -1 Then MsgBox(0, "Error", "Unable to open file.") Else If GuiCtrlRead($Username) = "" Then MsgBox (16,"ERROR", "Please enter the name of the person picking up or dropping off") Else FileWrite($file, $machine & " checked OUT by " & GUICtrlRead($Username) & " on " & @mon & "/" & @mday & "/" & @year & " at " & @hour & ":" & @min & ". Entry logged by " & @UserName & "." & @CRLF) FileClose($file) MsgBox (64,"Processed", "Record Submitted") Exit EndIF EndIf EndFunc ;------------------------------------------------------------------------------------------------------------------------------ ;Update Laptop number when machines are swapped out ;------------------------------------------------------------------------------------------------------------------------------ Func stateEdit($machine) If $file = -1 Then MsgBox(0, "Error", "Unable to open file.") Else If GuiCtrlRead($UserInput) = "" Then MsgBox (16,"ERROR", "Please enter the new LAT number") Else FileWrite($file, $machine & " = " & GUICtrlRead($UserInput) & @CRLF) FileClose($file) MsgBox (64,"Processed", "Update Submitted") Exit EndIF EndIf EndFunc
    1 point
  13. @rootx: I've now had a chance to examine your work environment as you posted it in your second zip. You need to upgrade to the latest version (2.1) of the bundle (you're apparently still using release 1.9); the bug you encounter (doubled underscore in split lines) has since been fixed.
    1 point
  14. Fasix, This UDF by jguinch will tell you all you need to know. kylomas
    1 point
  15. pluto41

    TPM status with wmi

    ; TPM Security Info Opt ( 'MustDeclareVars', 1 ) Local $objWMIService, $colItem, $objItem ; Declare Local $strComputer = "." ; Local Computer ; WMI Object $objWMIService = ObjGet ( "WinMgmts:{impersonationLevel=impersonate,AuthenticationLevel=pktprivacy}//" & $strComputer & "\root\CIMV2\Security\MicrosoftTpm" ) ; WMI Object check. If IsObj ( $objWMIService ) Then ConsoleWrite ( "Object YES" & @CRLF ) ; Debug console message Else ConsoleWrite ( "Object NO" & @CRLF ) Exit 1 ; Exit Script Object error / WMI MicrosoftTpm not found. EndIf $objItem = $objWMIService.InstancesOf ( "Win32_Tpm" ) For $colItems In $objItem ConsoleWrite ( "IsActivated : " & $colItems.IsActivated_InitialValue & @CRLF ) ConsoleWrite ( "IsEnabled : " & $colItems.IsEnabled_InitialValue & @CRLF ) ConsoleWrite ( "IsOwned : " & $colItems.IsOwned_InitialValue & @CRLF ) ConsoleWrite ( "SpecVersion : " & $colItems.SpecVersion & @CRLF ) ConsoleWrite ( "ManufacturerVersion : " & $colItems.ManufacturerVersion & @CRLF ) ConsoleWrite ( "ManufacturerVersionInfo : " & $colItems.ManufacturerVersionInfo & @CRLF ) ConsoleWrite ( "ManufacturerId : " & $colItems.ManufacturerId & @CRLF ) ConsoleWrite ( "PhysicalPresenceVersionInfo : " & $colItems.PhysicalPresenceVersionInfo & @CRLF ) Next Hi, I don't have TPM enabled and i am running Windows in a virtual machine. Anyway i narrowed your'e code a bit down and rewrote a little bit. Hope this works for you.
    1 point
  16. ripdad

    WMI Query v1.04

    There are a number of available programs for WMI that will show you information on Class Objects. After many hours of research and testing, this is my small version. It mainly serves as a reference. If you're working on a script, you'll still have to find an "example" on the web (if you can find one), as this program won't provide you with any. What will it provide? The script queries information from WMI on your computer. If the information exist, then you'll be able to view: - Data Types - Descriptions - Mappings - Origins - Syntax for Methods - System Properties for Classes - and Other Useful Information Sometimes, a particular class seems to be missing some information or has very little. If you find what it's "Origin" is... sometimes you can glean something from it's parent. -- Here are a few links from MSDN that might be of interest: WMI Reference http://msdn.microsoft.com/en-us/library/windows/desktop/aa394572(v=vs.85).aspx Standard WMI Qualifiers http://msdn.microsoft.com/en-us/library/windows/desktop/aa393651(v=vs.85).aspx MOF Data Types http://msdn.microsoft.com/en-us/library/windows/desktop/aa392392(v=vs.85).aspx -- Let me know if any problems. Thanks. Version: 1.04 WMI_Query.au3 Update: April 08, 2012 * added: Cache, saved in @AppDataDir\WMI_Query_Cache * added: _DeleteCache(), Press F9 to delete. * added: WM_GETMINMAXINFO(), GUI minimal resize. Update: April 09, 2012 * fixed: HTML tags (left and right arrows) in some WMI strings, causing some data not to display. Update: April 11, 2012 * fixed: Method Names that have a void CIMType. Would cause method name not to display. Update: May 22, 2012 Adjusted the height for the combo's. The x64 restriction has been removed.
    1 point
  17. @Valiante This should get you going $strComputer = "." $strUser = "" $strDomain = "domain" $strPassword = "" $Output="" $Output = $Output & "Computer: " & $strComputer & @CRLF $Output = $Output & "==========================================" & @CRLF $objSWbemLocator = ObjCreate("WbemScripting.SWbemLocator") $objWMIService = $objSWbemLocator.ConnectServer($strComputer,"root\CIMV2",$strUser, $strPassword) ;, "MS_409", "ntlmdomain:" & $strDomain) $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_ComputerSystem") For $objItem in $colItems ConsoleWrite($Output & $objItem.Name & @LF & @LF) ; returns the local CMP name !! Next Regards, ptrex
    1 point
×
×
  • Create New...