Hello again, i have a code that changes username to favorite, my problem is how to use ObjEvent() function to catch errors, i've red Help File and Forum's Topics but i can't understand too much😐
Here is a code (I've copied this codes from a user of AutoIt Forum):
$sOldUser = "Administrator" $sNewUser = "Admin" $oUser = ObjGet("WinNT://" & @ComputerName & "/" & $sOldUser & ",user") $oComputer = ObjGet("WinNT://" & @ComputerName) $oNewUser = $oComputer.MoveHere($oUser.ADsPath, $sNewUser) Thanks for your care, I'm new to AutoIt and days should be passed with my coding and practicing to don't bother you :)❤
Trying to figure out how to do CallByName on AutoIt COM objects due to the lack of being able to set properties within an Execute() statement
Several Ideas were Tried https://www.autoitscript.com/forum/topic/200129-set-object-properties-with-propertyname-and-value-taken-from-an-array/
I think this is the best; Patching the vtable of IDispatch so we can intercept a Fake function call ($obj.Au3_CallByName)
use it like this
Local $oDictionary = ObjCreate("Scripting.Dictionary") ; EXAMPLE Au3_CallByname_Init() ; (you can optionally provide a classname here but we patch the main Idispatch interface so really no need) $Au3_CallByName = "Add" ; Method we want to call $oDictionary.Au3_CallByName("Test", "Value") Au3_CallByname_Init(False) ; (Not Strictly Needed unhooked on exit) NOTE: Au3_CallByname_Init() doesn't have to be called at the top of the script, just call it before you need to call by name...
Code + Example
#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=y #AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** ;Au3CallByName, Bilgus Global $Au3_CallByName = 0 Local $hKernel32 = DllOpen("Kernel32.dll") OnAutoItExitRegister(__CallByNameCleanup) Func __CallByNameCleanup() Au3_CallByName_Init(False) ;Unload DllClose($hKernel32) EndFunc ;==>__CallByNameCleanup ; Takes a pointer to the v-table in a class and replaces specified member Id in it to a new one. Func __HookVTableEntry($pVtable, $iVtableOffset, $pHook, ByRef $pOldRet) ;;https://www.autoitscript.com/forum/topic/107678-hooking-into-the-idispatch-interface/ Local Const $PAGE_READWRITE = 0x04 Local $tpVtable = DllStructCreate("ptr", $pVtable) Local $szPtr = DllStructGetSize($tpVtable) Local $pFirstEntry, $pEntry, $tEntry, $aCall, $flOldProtect, $bStatus ; Dereference the vtable pointer $pFirstEntry = DllStructGetData($tpVtable, 1) $pEntry = $pFirstEntry + ($iVtableOffset * $szPtr) ; Make the memory free for all. Yay! $aCall = DllCall($hKernel32, "int", "VirtualProtect", "ptr", $pEntry, "long", $szPtr, "dword", $PAGE_READWRITE, "dword*", 0) If @error Or Not $aCall Then ConsoleWriteError("Error: Failed To hook vTable" & @CRLF) Return False EndIf $flOldProtect = $aCall $tEntry = DllStructCreate("ptr", $pEntry) $pOldRet = DllStructGetData($tEntry, 1) If $pOldRet <> $pHook Then DllStructSetData($tEntry, 1, $pHook) $bStatus = True Else ;Already Hooked ConsoleWriteError("Error: vTable is already hooked" & @CRLF) $bStatus = False EndIf ;put the memory protect back how we found it DllCall($hKernel32, "int", "VirtualProtect", "ptr", $pEntry, "long", $szPtr, "dword", $flOldProtect, "dword*", 0) Return $bStatus EndFunc ;==>__HookVTableEntry ; Everytime autoit wants to call a method, get or set a property in a object it needs to go to ; IDispatch::GetIDsFromNames. This is our version of that function, note that by defining this ourselves ; we can fool autoit to believe that the object supports a lot of different properties/methods. Func __IDispatch_GetIDsFromNames($pSelf, $riid, $rgszNames, $cNames, $lcid, $rgDispId) Local Const $CSTR_EQUAL = 0x02 Local Const $LOCALE_SYSTEM_DEFAULT = 0x800 Local Const $DISP_E_UNKNOWNNAME = 0x80020006 Local Static $pGIFN = __Pointer_GetIDsFromNames() Local Static $tpMember = DllStructCreate("ptr") If $Au3_CallByName Then Local $hRes, $aCall, $tMember ;autoit only asks for one member $aCall = DllCall($hKernel32, 'int', 'CompareStringW', 'dword', $LOCALE_SYSTEM_DEFAULT, 'dword', 0, 'wstr', "Au3_CallByName", 'int', -1, _ 'struct*', DllStructGetData(DllStructCreate("ptr[" & $cNames & "]", $rgszNames), 1, 1), 'int', -1) If Not @error And $aCall = $CSTR_EQUAL Then ;ConsoleWrite("CallByName: " & $Au3_CallByName & @CRLF) $tMember = DllStructCreate("wchar[" & StringLen($Au3_CallByName) + 1 & "]") DllStructSetData($tMember, 1, $Au3_CallByName) DllStructSetData($tpMember, 1, DllStructGetPtr($tMember)) $rgszNames = $tpMember $Au3_CallByName = 0 EndIf EndIf ;Call the original GetIDsFromNames $hRes = DllCallAddress("LRESULT", $pGIFN, "ptr", $pSelf, "ptr", $riid, _ "struct*", $rgszNames, "dword", $cNames, "dword", $lcid, "ptr", $rgDispId) If @error Then ConsoleWrite("Error: GetIDsFromNames: " & @error & @CRLF) Return $DISP_E_UNKNOWNNAME EndIf Return $hRes EndFunc ;==>__IDispatch_GetIDsFromNames Func __Pointer_GetIDsFromNames($ptr = 0) Local Static $pOldGIFN = $ptr If $ptr <> 0 Then $pOldGIFN = $ptr Return $pOldGIFN EndFunc ;==>__Pointer_GetIDsFromNames Func Au3_CallByName_Init($bHook = True, $classname = "shell.application") Local Const $iOffset_GetIDsFromNames = 5 Local Static $IDispatch_GetIDsFromNames_Callback = 0 Local $oObject, $pObject, $pHook, $pOldGIFN If $bHook Then If $IDispatch_GetIDsFromNames_Callback = 0 Then $IDispatch_GetIDsFromNames_Callback = DllCallbackRegister("__IDispatch_GetIDsFromNames", "LRESULT", "ptr;ptr;ptr;dword;dword;ptr") EndIf $pHook = DllCallbackGetPtr($IDispatch_GetIDsFromNames_Callback) Else $pHook = __Pointer_GetIDsFromNames() If $pHook <= 0 Then Return ;Already Unloaded EndIf $oObject = ObjCreate($classname) $pObject = DllStructSetData(DllStructCreate("ptr"), 1, $oObject) If __HookVTableEntry($pObject, $iOffset_GetIDsFromNames, $pHook, $pOldGIFN) Then __Pointer_GetIDsFromNames($pOldGIFN) ;Save the original pointer to GetIDsFromNames If Not $bHook Then DllCallbackFree($IDispatch_GetIDsFromNames_Callback) $IDispatch_GetIDsFromNames_Callback = 0 EndIf Else ;Error EndIf $oObject = 0 EndFunc ;==>Au3_CallByName_Init ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;TESTS; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Au3_CallByName_Init() #include <ie.au3> Global $oRegistrationInfo = _IECreate() Global $aRegistrationInfo = ['Left=10', 'Top= 10', 'Width=450', 'Height=600'] Global $oObject = $oRegistrationInfo Local $oDictionary = ObjCreate("Scripting.Dictionary") Local $oDictionary2 = ObjCreate("Scripting.Dictionary") ;Au3_CallByName_Init($oObject) __TS_TaskPropertiesSet($oObject, $aRegistrationInfo) MsgBox(0, "Info", "Press OK to exit") $oRegistrationInfo.quit $oRegistrationInfo = 0 $oObject = 0 Sleep(1000) For $i = 1 To 10 $Au3_CallByName = "Add" $oDictionary.Au3_CallByName("test1:" & $i, "Dictionary Item: " & $i) Next $Au3_CallByName = "keys" For $sKey In $oDictionary.Au3_CallByName() For $j = 0 To 1 $Au3_CallByName = ($j = 0) ? "Item" : "Exists" ConsoleWrite($sKey & " -> " & $oDictionary.Au3_CallByName($sKey) & @CRLF) Next Next Au3_CallByName_Init(False) ;Unload Au3_CallByName_Init() Local $aRegistrationInfo = ['Left=1000', 'Width=450'] ConsoleWrite(@CRLF & "NEW IE" & @CRLF & @CRLF) $oRegistrationInfo = _IECreate() __TS_TaskPropertiesSet($oRegistrationInfo, $aRegistrationInfo) MsgBox(0, "Info", "Press OK to exit") $oRegistrationInfo.quit For $i = 1 To 10 $Au3_CallByName = "Add" $oDictionary2.Au3_CallByName("test2:" & $i, "Dictionary Item: " & $i) Next $Au3_CallByName = "keys" For $sKey In $oDictionary2.Au3_CallByName() For $j = 0 To 1 $Au3_CallByName = ($j = 0) ? "Item" : "Exists" ConsoleWrite($sKey & " -> " & $oDictionary2.Au3_CallByName($sKey) & @CRLF) Next Next Au3_CallByName_Init(False) ;Unload (Not Strictly Needed, Done on Script Close) Func __TS_TaskPropertiesSet(ByRef $oObject, $aProperties) Local $aTemp If IsArray($aProperties) Then For $i = 0 To UBound($aProperties) - 1 $aTemp = StringSplit($aProperties[$i], "=", 2) ; 2 -> $STR_NOCOUNT) If @error Then ContinueLoop ConsoleWrite("Command: $oObject." & $aTemp & " = " & $aTemp & @CRLF) $Au3_CallByName = $aTemp $oObject.Au3_CallByName = $aTemp ConsoleWrite("Result : " & Hex(@error) & @CRLF) ; If @error Then Return SetError(1, @error, 0) Next EndIf EndFunc ;==>__TS_TaskPropertiesSet
I have a smartphone and I use it to access my email. However, when composing an email on it I have a problem. My list of phone contacts on the phone is very different from my list of email contacts in my Thunderbird desktop app. I use my Gmail address book to store primarily phone contacts, and I use Thunderbird for my list of email contacts. I wanted a way to get my Thunderbird contact list onto my smartphone to be able to compose emails to addresses in that list. Here's my solution.
I wrote a script to export my Thunderbird Personal Address Book to a csv file. It then reads that file and re-writes it with html wrappers around the data to make it into a nicely formatted web page. It then uploads the htm file to my website. On my smartphone, I created a shortcut to the file's URL and whenever I click it, I get the list displayed. Each contact shows name and email address along with a COPY button that will put the address into the clipboard. Then in my email client, I can easily paste that address into it. Alternatively, clicking on the actual email link will open a new message dialog in your email client with that address already entered.
To use the app, all you need to do is use Thunderbird and have a webserver available. You'll need to download the FTPEX.AU3 file from this website and make a few changes to some constants around line 17 for FTP login info, etc.
The following function successfully connects to and uploads a local text file named user.dat
I have checked the data being written to the text file when it is created locally using a MsgBox and it appears exactly how it should be written to the file. If I comment out the FileDelete and go and open the file locally it is as expected.
However when I download the file from the FTP server and open it up the text that should be at the end of the file is missing. With each subsequent run more characters are missing.
I added the Sleep(5000) in case the function was closing the FTP connection too quickly before the file could be fully written but it makes no difference. The user.dat file is (should be) approximately 100 bytes so it is tiny.
Any idea why this is happening?
Func UpdateUserData() ; Upload the modified user.dat file Local $hOpen = _FTP_Open("myftp") Local $hConn = _FTP_Connect($hOpen, "my.ftp.server", "user", "pass", 1, 0, 1, 2) If @error Then MsgBox(16, "Error", "Connection failed" & @CRLF & @CRLF & "Please contact support") _FTP_Close($hConn) _FTP_Close($hOpen) Exit EndIf _FTP_FilePut($hConn, @TempDir & "\user.dat", "user.dat") ; Upload the new user.dat file Sleep(5000) If @error <> 0 Then MsgBox(16, "Error", "Couldn't transmit data" & @CRLF & @CRLF & "Please contact support") _FTP_Close($hConn) _FTP_Close($hOpen) Exit EndIf _FTP_Close($hConn) _FTP_Close($hOpen) FileDelete(@TempDir & "\user.dat") EndFunc