trancexx Posted January 22, 2009 Posted January 22, 2009 (edited) You know that SciTE quality to show how many instances of it is running and what is current one that you view. Information about this is in SciTE window title. Something like: "path\name - SciTE [2 of 7]"I find that very useful an wanted to implement that in one of my script. This is the idea and the procedure:1. When script starts call function CreateSemaphore from kernel32.dll. Use unique string (GUID)2. Call ReleaseSemaphore function from kernel32 to increas the count of the semaphore object by one3. Register new unique window message using function RegisterWindowMessage from user32.dll4. Use function SendMessageCallback from user32.dll to send message to all top-level windows in the system. This message will be caught only by our windows. This is to say "Hey I'm here and I'm your new instance!"5. Use GUIRegisterMsg() to register function ( _IntermediaryFunction) that deals with enumeration. Message ID is return value of RegisterWindowMessage (step 3)To make it work properly few more steps needs to be done when script is about to exit:6. Get handle of the semaphore object (that is done for example calling CreateSemaphore function again)7. Decrease the semaphore's count by one calling function WaitForSingleObject from kernel32.dll8. Use SendMessageCallback from user32.dll to announce to other windows intention to exit.Other windows processes that message and updates their titles (_IntermediaryFunction from step 5).And that's it!!!Example script:expandcollapse popupGlobal $iInstanceCurrent, $iInstancesOverall _NumInst("SomeUniqueString") Global $iMessage = _RegisterWindowMessage("AnotherUniqueString") Global $hGui = GUICreate("My Example script [" & $iInstanceCurrent & " of " & $iInstancesOverall & "]") GUISetState(@SW_SHOW) While 1 If GUIGetMsg() = -3 Then ExitLoop WEnd Func _NumInst($sName) Local $a_hCall = DllCall("kernel32.dll", "hwnd", "CreateSemaphore", _ "ptr", 0, _ "int", 1, _ "int", 999, _ "str", $sName) If @error Or Not $a_hCall[0] Then Return SetError(1, 0, "") EndIf Local $hSemaphore = $a_hCall[0] $a_iCall = DllCall("kernel32.dll", "int", "ReleaseSemaphore", "hwnd", $hSemaphore, "int", 1, "int*", 0) If @error Or Not $a_iCall[0] Then Return SetError(2, 0, "") EndIf $iInstanceCurrent = $a_iCall[3] ; global variable $iInstancesOverall = $a_iCall[3] ; this too, initially they are the same Return SetError(0, 0, 1) EndFunc ;==>_NumInst Func _RegisterWindowMessage($sMessage) Local $a_iCall = DllCall("user32.dll", "dword", "RegisterWindowMessage", "str", $sMessage) If @error Or Not $a_iCall[0] Then Return SetError(1, 0, "") EndIf Local $iMessage = $a_iCall[0] $a_iCall = DllCall("user32.dll", "int", "SendMessageCallback", _ "hwnd", 0xFFFF, _ "dword", $iMessage, _ "int", $iInstanceCurrent, _ "int", 0, _ "ptr", 0, _ "dword", 0) If @error Or Not $a_iCall[0] Then Return SetError(2, 0, "") EndIf GUIRegisterMsg($iMessage, "_IntermediaryFunction") Return SetError(0, 0, $iMessage) EndFunc ;==>_RegisterWindowMessage Func _IntermediaryFunction($hHwnd, $iMsg, $wParam, $lParam) $wParam = BitOR($wParam, 0) $lParam = BitOR($lParam, 0) If $wParam > $iInstanceCurrent Then $iInstancesOverall += 1 EndIf If $lParam Then $iInstancesOverall -= 1 If $lParam <= $iInstanceCurrent Then $iInstanceCurrent -= 1 EndIf EndIf WinSetTitle($hGui, 0, "My Example script [" & $iInstanceCurrent & " of " & $iInstancesOverall & "]") EndFunc ;==>_IntermediaryFunction Func OnAutoItExit() If $iMessage Then Local $a_hCall = DllCall("kernel32.dll", "hwnd", "CreateSemaphore", _ "ptr", 0, _ "int", 1, _ "int", 999, _ "str", "SomeUniqueString") If Not @error Then Local $hSemaphore = $a_hCall[0] Local $a_iCall = DllCall("kernel32.dll", "dword", "WaitForSingleObject", _ "hwnd", $hSemaphore, _ "dword", 0) If Not @error Then $a_iCall = DllCall("user32.dll", "int", "SendMessageCallback", _ "hwnd", 0xFFFF, _ "dword", $iMessage, _ "int", 0, _ "int", $iInstanceCurrent, _ "ptr", 0, _ "dword", 0) EndIf EndIf EndIf EndFunc ;==>OnAutoItExitI've made ResHacker wannabe update. Newly attached script is fully implementing this method.Link to that scriptCheck it out, it's totaly coolBtw, I find moderator's (or whosever) act regarding this topic to be almost shallow. Code was posted if that was the reason to move this post. Very superficial.edit:topsy Edited January 23, 2009 by trancexx ♡♡♡ . eMyvnE
ptrex Posted January 23, 2009 Posted January 23, 2009 @trancexx A shame no one reacted on this. Very nicely done regards, ptrex Contributions :Firewall Log Analyzer for XP - Creating COM objects without a need of DLL's - UPnP support in AU3Crystal Reports Viewer - PDFCreator in AutoIT - Duplicate File FinderSQLite3 Database functionality - USB Monitoring - Reading Excel using SQLRun Au3 as a Windows Service - File Monitor - Embedded Flash PlayerDynamic Functions - Control Panel Applets - Digital Signing Code - Excel Grid In AutoIT - Constants for Special Folders in WindowsRead data from Any Windows Edit Control - SOAP and Web Services in AutoIT - Barcode Printing Using PS - AU3 on LightTD WebserverMS LogParser SQL Engine in AutoIT - ImageMagick Image Processing - Converter @ Dec - Hex - Bin -Email Address Encoder - MSI Editor - SNMP - MIB ProtocolFinancial Functions UDF - Set ACL Permissions - Syntax HighLighter for AU3ADOR.RecordSet approach - Real OCR - HTTP Disk - PDF Reader Personal Worldclock - MS Indexing Engine - Printing ControlsGuiListView - Navigation (break the 4000 Limit barrier) - Registration Free COM DLL Distribution - Update - WinRM SMART Analysis - COM Object Browser - Excel PivotTable Object - VLC Media Player - Windows LogOnOff Gui -Extract Data from Outlook to Word & Excel - Analyze Event ID 4226 - DotNet Compiler Wrapper - Powershell_COM - New
Manko Posted January 23, 2009 Posted January 23, 2009 ptrex said: @trancexxA shame no one reacted on this.I just saw it now. Looking REAL good!!/Manko Yes i rush things! (I sorta do small bursts inbetween doing nothing.) Things I have rushed and reRushed:* ProDLLer - Process manager - Unload viri modules (dll) and moore...* _WinAPI_ProcessListOWNER_WTS() - Get Processes owner list...* _WinAPI_GetCommandLineFromPID() - Get commandline of target process...* _WinAPI_ThreadsnProcesses() Much info if expanded - optional Indented "Parent/Child"-style Processlist. Moore to come... eventually...
Skrip Posted January 23, 2009 Posted January 23, 2009 Wow. Very nice, I never would have thought to do this. [left][sub]We're trapped in the belly of this horrible machine.[/sub][sup]And the machine is bleeding to death...[/sup][sup][/sup][/left]
trancexx Posted February 13, 2009 Author Posted February 13, 2009 This is by using OpenSemaphore function (more proper maybe) to get handle to the semaphore object on exit (first post script is using CreateSemaphore again). Also messages here are sent by SendNotifyMessage since I'm not using callback function (option) of SendMessageCallback function.New script:expandcollapse popupGlobal $iInstanceCurrent, $iInstancesOverall _NumInst("SomeUniqueString") Global $iMessage = _RegisterWindowMessage("AnotherUniqueString") Global $hGui = GUICreate("My Example script [" & $iInstanceCurrent & " of " & $iInstancesOverall & "]") GUISetState(@SW_SHOW) While 1 If GUIGetMsg() = -3 Then ExitLoop WEnd Func _NumInst($sName) Local $a_hCall = DllCall("kernel32.dll", "hwnd", "CreateSemaphore", _ "ptr", 0, _ "int", 1, _ ; initial count "int", 999, _ ; max count "str", $sName) ; name of the semaphore object If @error Or Not $a_hCall[0] Then Return SetError(1, 0, "") EndIf Local $hSemaphore = $a_hCall[0] $a_iCall = DllCall("kernel32.dll", "int", "ReleaseSemaphore", "hwnd", $hSemaphore, "int", 1, "int*", 0) If @error Or Not $a_iCall[0] Then Return SetError(2, 0, "") EndIf $iInstanceCurrent = $a_iCall[3] ; global variable $iInstancesOverall = $a_iCall[3] ; this too, initially they are the same Return SetError(0, 0, 1) EndFunc ;==>_NumInst Func _RegisterWindowMessage($sMessage) Local $a_iCall = DllCall("user32.dll", "dword", "RegisterWindowMessage", "str", $sMessage) If @error Or Not $a_iCall[0] Then Return SetError(1, 0, "") EndIf Local $iMessage = $a_iCall[0] $a_iCall = DllCall("user32.dll", "int", "SendNotifyMessage", _ "hwnd", 0xFFFF, _ ; HWND_BROADCAST "dword", $iMessage, _ "int", $iInstanceCurrent, _ "int", 0) If @error Or Not $a_iCall[0] Then Return SetError(2, 0, "") EndIf GUIRegisterMsg($iMessage, "_IntermediaryFunction") Return SetError(0, 0, $iMessage) EndFunc ;==>_RegisterWindowMessage Func _IntermediaryFunction($hHwnd, $iMsg, $wParam, $lParam) $wParam = BitOR($wParam, 0) $lParam = BitOR($lParam, 0) If $wParam > $iInstanceCurrent Then $iInstancesOverall += 1 EndIf If $lParam Then $iInstancesOverall -= 1 If $lParam <= $iInstanceCurrent Then $iInstanceCurrent -= 1 EndIf EndIf WinSetTitle($hGui, 0, "My Example script [" & $iInstanceCurrent & " of " & $iInstancesOverall & "]") EndFunc ;==>_IntermediaryFunction Func OnAutoItExit() If $iMessage Then Local $a_hCall = DllCall("kernel32.dll", "hwnd", "OpenSemaphore", _ "dword", 0x100000, _ ; SYNCHRONIZE "int", 0, _ "str", "SomeUniqueString") ; name of our semaphore If Not @error Then Local $hSemaphore = $a_hCall[0] Local $a_iCall = DllCall("kernel32.dll", "dword", "WaitForSingleObject", _ "hwnd", $hSemaphore, _ "dword", 0) If Not @error Then $a_iCall = DllCall("user32.dll", "int", "SendNotifyMessage", _ "hwnd", 0xFFFF, _ ; HWND_BROADCAST "dword", $iMessage, _ "int", 0, _ "int", $iInstanceCurrent) EndIf EndIf EndIf EndFunc ;==>OnAutoItExit ♡♡♡ . eMyvnE
Apzo Posted February 16, 2009 Posted February 16, 2009 Interesting for sure, but what is it for ?I understand it deals with multiple process, but what is the problem solved with this script ?Without a concrete example it's hard figure out BTW I'm interested : I try to have my plugins talking with a core server but the IPC part is rather hard to handle.If this can help me, I'd be glad to know how Apzo. ptrex said: @trancexxA shame no one reacted on this.Very nicely done regards,ptrex All the pop3 functions.Rsync your files on your USB key (or anywhere else)
trancexx Posted February 16, 2009 Author Posted February 16, 2009 Apzo said: Interesting for sure, but what is it for ?I understand it deals with multiple process, but what is the problem solved with this script ?Without a concrete example it's hard figure out BTW I'm interested : I try to have my plugins talking with a core server but the IPC part is rather hard to handle.If this can help me, I'd be glad to know how Apzo.There are three examples posted. I can't imagine more concrete examples. Just double click (run) each of that scripts more than once at the same time and observe the differences in window titles. Close some windows, run some more, etc...About solved problems... I guess nothing is solved only few more problems possibly created. ♡♡♡ . eMyvnE
wraithdu Posted May 20, 2009 Posted May 20, 2009 Actually, I used this technique to solve a problem recently in a script I want to release. The problem was with system context menu integration. In the normal system context menu (NOT a shell extension) when you perform an action on more than one file, then an instance of the associated process is launched for each file selected. I needed a way to control this so that the first instance of the process would launch and perform its task, then the others would wait for it to be ready and ONE-AT-A-TIME pass some data using WM_COPYDATA to the initial instance for processing. Semaphores worked great. The other challenge with the whole process is that in AutoIt you're not supposed to block a function called from GuiRegisterMessage() with anything that takes a long time (like from a WM_COPYDATA message). You're supposed to return to the main script as fast as possible. I solved that problem, but it was causing major synchronization problems with the multiple instances. Again, semaphores solved this nicely. Now each additional instance waits for its slot, then sends the message to the main instance, which procsses the message and returns immediately. Then the data is processed back in the main script, and after it is finished another semaphore is released to allow the next waiting instance to send its data.
stinson6016 Posted May 21, 2009 Posted May 21, 2009 can you send other data between the scripts too? still catching on to working with dlls Gnatwork Networks
wraithdu Posted May 21, 2009 Posted May 21, 2009 Depending on the method you can send any kind of data between processes. See my script HERE for an example using semaphores and WM_COPYDATA to communicate between script instances.A more manual method would be physically allocating memory in another process, writing the data, and sending a message to the process to read the memory / data.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now