singleinstance off and keep only 1st instance of gui/script

Post your working scripts, libraries and tools for AHK v1.1 and older
ananthuthilakan
Posts: 188
Joined: 08 Jul 2019, 05:37
Contact:

singleinstance off and keep only 1st instance of gui/script

04 May 2023, 16:20

keep1stinstance.ahk

Code: Select all

;{========[do not relaunch the script as another instance if its already running instead show existing gui]=========================================


;~ author: ananthuthilakan
;~ website: ananthuthilakan.com
;~ github: https://github.com/ananthuthilakan/singleInstanceKeep
;~ do not relaunch the script as another instance if its already running 

;~ use case 
;~ prevent data loss
;~ singleinstance force fails sometimes
;~ singleinstance off creates multiple instances

;~ how to use 
;~ Add #SingleInstance Off
;~ Call the function keep1stinstance() immediatly after gui, show , Hide ; optional variable is gui name e.g keep1stinstance("testgui")
;~ example script 

/*
#include keep1stinstance.ahk
#SingleInstance Off
message:="my message" ; to send an array. convert array into json using  https://github.com/G33kDude/cJson.ahk/releases
gui,testgui: add, button ,, ok
gui,testgui: show , hide w400 h400 ,testtitle
keep1stinstance("testgui",message) ; pass the guiname if it has or leave it blank , keep1stinstance([guiname,message])
return

testguiguiClose:  ; dont forget to add this 
exitapp
*/

;==================================================================================================================================================


Receive_WM_COPYDATA(wParam, lParam)
{
StringAddress := NumGet(lParam + 2*A_PtrSize)  
Global recieved_message := StrGet(StringAddress)  
showgui1stinstance()
MsgBox, 0, recived message,% "the message from 2nd instance is [ " recieved_message " ]", 2 ; this is for testing , do what you want with the recieved message here
return true  ; Returning 1 (true) is the traditional way to acknowledge this message.
}



keep1stinstance(guiname:="1",StringToSend:="alreadyExist"){
cPID:=DllCall("GetCurrentProcessId"), cName:=A_IsCompiled ? A_ScriptName : ComObjGet("winmgmts:")
.ExecQuery("Select * from Win32_Process Where " cPID "=ProcessId")._NewEnum()[cPInf] ? cPInf.Name :"" ;AppNane|AutoHotkey.exe
FOR proc in ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process")
IF (proc.Name = cName) && (proc.ProcessID != cPID) && (A_IsCompiled ? True : InStr(proc.CommandLine, A_ScriptFullPath))
TargetScriptTitle:= "ahk_pid " . proc.ProcessID
;~ iniRead,winid,windowid.ini,winid,winid
result := Send_WM_COPYDATA(StringToSend, TargetScriptTitle)
if (result=1){
;~ msgbox, already exist  `n it will show the already existing instance 
exitapp
return
}
OnMessage(0x004A, "Receive_WM_COPYDATA")
showgui1stinstance(guiname)
}

showgui1stinstance(guiname:=""){
static guiname1
if (guiname)
guiname1:= guiname
try
gui,%guiname1% : show
}


Send_WM_COPYDATA(ByRef StringToSend, ByRef TargetScriptTitle)  ; ByRef saves a little memory in this case.
; This function sends the specified string to the specified window and returns the reply.
; The reply is 1 if the target window processed the message, or 0 if it ignored it.
{
    VarSetCapacity(CopyDataStruct, 3*A_PtrSize, 0)  ; Set up the structure's memory area.
    ; First set the structure's cbData member to the size of the string, including its zero terminator:
    SizeInBytes := (StrLen(StringToSend) + 1) * (A_IsUnicode ? 2 : 1)
    NumPut(SizeInBytes, CopyDataStruct, A_PtrSize)  ; OS requires that this be done.
    NumPut(&StringToSend, CopyDataStruct, 2*A_PtrSize)  ; Set lpData to point to the string itself.
    Prev_DetectHiddenWindows := A_DetectHiddenWindows
    Prev_TitleMatchMode := A_TitleMatchMode
    DetectHiddenWindows On
    SetTitleMatchMode 2
    TimeOutTime := 4000  ; Optional. Milliseconds to wait for response from receiver.ahk. Default is 5000
    ; Must use SendMessage not PostMessage.
    SendMessage, 0x004A, 0, &CopyDataStruct,, %TargetScriptTitle%,,,, %TimeOutTime% ; 0x004A is WM_COPYDATA.
    DetectHiddenWindows %Prev_DetectHiddenWindows%  ; Restore original setting for the caller.
    SetTitleMatchMode %Prev_TitleMatchMode%         ; Same.
    return ErrorLevel  ; Return SendMessage's reply back to our caller.
}

;}===================================================================================================================================

examples
https://github.com/ananthuthilakan/singleInstanceKeep/blob/main/example2.ahk
Last edited by ananthuthilakan on 05 May 2023, 23:53, edited 4 times in total.

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: Chunjee, kaka2 and 93 guests