Jump to content



Photo

Enforce Single Instance of Program via WM_COPYDATA


  • Please log in to reply
9 replies to this topic

#1 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,164 posts

Posted 15 December 2009 - 11:57 AM

For an example on how to send and receive data between different instances of the same script and which passes commandline parameters to the first instance via WM_COPYDATA take a look at post 2.

Just a short snippet which came to my mind as the _Singleton() standard UDF failed on my work-notebook for me (CreateMutexW returns winapi-error 126 - "The specified module could not be found" :evil:, I just assume it interferes with one of the 72 ;) processes running).

AutoIt         
#cs ----------------------------------------------------------------------------     AutoIt Version: 3.3.0.0     Author:         KaFu     Script Function:     _EnforceSingleInstance() function, Standard _Singleton() UDF failed on some machines for me #ce ---------------------------------------------------------------------------- _EnforceSingleInstance('e15ff08b-84ac-472a-89bf-5f92db683165') ; any 'unique' string; created with <a href='http://www.guidgen.com/Index.aspx' class='bbc_url' title='External link' rel='norewrite nofollow external'>http://www.guidgen.com/Index.aspx</a> MsgBox(0, "", "Test") Func _EnforceSingleInstance($GUID_Program)     If $GUID_Program = "" Then Return SetError(1,'',1)     if IsHWnd(WinGetHandle($GUID_Program)) then         MsgBox(0,"Test","Second instance, will exit now...")         Exit     EndIf     AutoItWinSetTitle($GUID_Program)     Return WinGetHandle($GUID_Program) EndFunc   ;==>_EnforceSingleInstance


Should work as long as the key is really 'unique' (as unique as it gets :evil: ), and script is not complied as CUI (I'm not sure but I assume then there is no default AutoItWin).

Edited by KaFu, 10 April 2010 - 08:24 AM.






#2 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,164 posts

Posted 15 December 2009 - 04:31 PM

And while playing around... here is a version which passes commandline parameters to first instance via WM_COPYDATA before exiting...

Compile and start multiple times with different commandline parameters to see whats happening...

AutoIt         
#NoTrayIcon #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> $hwnd_AutoIt = _EnforceSingleInstance('e15ff08b-84ac-472a-89bf-5f92db683165') ; any 'unique' string; created with <a href='http://www.guidgen.com/Index.aspx' class='bbc_url' title='External link' rel='norewrite nofollow external'>http://www.guidgen.com/Index.aspx</a> Opt("TrayIconHide", 1) $hGUI = GUICreate("My GUI " & $hwnd_AutoIt,300,300,Default,Default) ; will create a dialog box that when displayed is centered $label = GUICtrlCreateLabel($CmdLineRaw,10,10,300,100) GUISetState(@SW_SHOW) ; will display an empty dialog box ControlSetText($hwnd_AutoIt,'',ControlGetHandle($hwnd_AutoIt,'','Edit1'),$hGUI) ; to pass hWnd of main GUI to AutoIt default GUI GUIRegisterMsg($WM_COPYDATA, "WM_COPYDATA") While 1     sleep(10)     $msg = GUIGetMsg()     If $msg = $GUI_EVENT_CLOSE Then ExitLoop WEnd GUIDelete() Func _EnforceSingleInstance($GUID_Program = "")     If $GUID_Program = "" Then Return     $hwnd = WinGetHandle($GUID_Program)     If IsHWnd($hwnd) Then         $hwnd_Target = ControlGetText($hwnd,'',ControlGetHandle($hwnd,'','Edit1'))         WM_COPYDATA_SendData(HWnd($hwnd_Target), $CmdLineRaw)         Exit     EndIf     AutoItWinSetTitle($GUID_Program)     Return WinGetHandle($GUID_Program) EndFunc   ;==>_EnforceSingleInstance Func WM_COPYDATA($hWnd, $MsgID, $wParam, $lParam)     ; <a href='http://www.autoitscript.com/forum/index.php?showtopic=105861&view=findpost&p=747887' class='bbc_url' title='' rel='norewrite'>http://www.autoitscript.com/forum/index.php?showtopic=105861&view=findpost&p=747887</a>     ; Melba23, based on code from Yashied     Local $tCOPYDATA = DllStructCreate("ulong_ptr;dword;ptr", $lParam)     Local $tMsg = DllStructCreate("char[" & DllStructGetData($tCOPYDATA, 2) & "]", DllStructGetData($tCOPYDATA, 3))     $msg = DllStructGetData($tMsg, 1)     if $msg = " " then         GUICtrlSetData($label, "")     else         GUICtrlSetData($label, DllStructGetData($tMsg, 1))     endif     Return 0 EndFunc   ;==>WM_COPYDATA Func WM_COPYDATA_SendData($hWnd, $sData)     If Not IsHWnd($hWnd) Then Return 0     if $sData = "" then $sData = " "     Local $tCOPYDATA, $tMsg     $tMsg = DllStructCreate("char[" & StringLen($sData) + 1 & "]")     DllStructSetData($tMsg, 1, $sData)     $tCOPYDATA = DllStructCreate("ulong_ptr;dword;ptr")     DllStructSetData($tCOPYDATA, 2, StringLen($sData) + 1)     DllStructSetData($tCOPYDATA, 3, DllStructGetPtr($tMsg))     $Ret = DllCall("user32.dll", "lparam", "SendMessage", "hwnd", $hWnd, "int", $WM_COPYDATA, "wparam", 0, "lparam", DllStructGetPtr($tCOPYDATA))     If (@error) Or ($Ret[0] = -1) Then Return 0     Return 1 EndFunc   ;==>WM_COPYDATA_SendData

Edited by KaFu, 23 November 2011 - 10:07 PM.


#3 Manadar

Manadar

    Taking a REST.

  • MVPs
  • 10,714 posts

Posted 15 December 2009 - 04:49 PM

Why do you set a default parameter when in the next line you are enforcing the user not to enter a use the default parameter anyway?

Edited by Manadar, 15 December 2009 - 04:49 PM.


#4 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,164 posts

Posted 15 December 2009 - 05:55 PM

Why do you set a default parameter when in the next line you are enforcing the user not to enter a use the default parameter anyway?

Lazyness, copy&paste... corrected...

#5 Manadar

Manadar

    Taking a REST.

  • MVPs
  • 10,714 posts

Posted 15 December 2009 - 07:10 PM

I really like your second implementation. Good job.

#6 Ascend4nt

Ascend4nt

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 1,073 posts

Posted 09 April 2010 - 10:50 PM

Hey, this is a pretty neat workaround. I didn't even know about the 'AutoItWinSetTitle' function! Go figure. I like the WM_COPYDATA use too - I had intended on writing something that would pass parameters to an already-running program in the future. Now i don't have to do the work :(

#7 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,164 posts

Posted 10 April 2010 - 08:27 AM

Hey, this is a pretty neat workaround.

Thanks for the praise :), nice to hear, especially from you :(.

This is how I balance the access to the Sqlite DB between searching and reporting instance in SMF (two instances of smf.exe running at the same time to give instant access to results).

And btw, a 4 star rating for this post? Someone didn't seem understand what's going on here :) ...

Edited by KaFu, 10 April 2010 - 08:30 AM.


#8 guinness

guinness

    guinness

  • MVPs
  • 10,347 posts

Posted 10 September 2010 - 11:40 AM

I posted on the General Help and Support about getting your example of WM_COPYDATA to work in x64 and Yashied kindly replied with a solution, replace the following instances of "dword;dword;ptr" to "ulong_ptr;dword;ptr".

Here is the post.

Example List: _AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_DesktopDimensions()_DisplayPassword()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUISetIcon()_Icon_Clear()/_Icon_Set()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringIsValid()_StringReplaceWholeWord()_StringStripChar()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()AutoIt SearchAutoIt3 PortableAutoItWinGetTitle()/AutoItWinSetTitle()CodingFileInstallrGeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIGetBkColor()LockFile()PasteBinSciTE JumpSignature CreatorWM_COPYDATAMore Examples...Updated: 11/04/2013


#9 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,164 posts

Posted 10 September 2010 - 12:41 PM

Followed that post, thanks for the addition ;).

#10 dexto

dexto

    Polymath

  • Active Members
  • PipPipPipPip
  • 239 posts

Posted 28 September 2010 - 05:57 PM

Very interesting! WM_COPYDATA implementation should be a part of standard includes and documented in a help file.
Too lazy for anything other then AutoIT.




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users