GUI Application: Single instance to capture parameters on repeated launch

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
Gavin
Posts: 12
Joined: 14 Jul 2020, 03:35

GUI Application: Single instance to capture parameters on repeated launch

11 Apr 2023, 07:28

Hi,

I have been using Hiedit.dll(4.0.04),HiEdit.ahk and Ahk2Exe.exe to write an editor application.

In general, I am very happy with the result (no text wrapping - but that's ok). From within the application, I can open and close files with the dialogs or using drag and drop.

However, I am having trouble with SingleInstance. When talking about text editors, single instance usually means "any repeated attempts to launch the editor will simply revert to the first running instance AND open any new filename parameter in a new tab".

I use an Xtree like file manager, and would like to be able to leave the editor open and then open further files by calling the exe with a filename parameter.

The top of my code is currently:

Code: Select all

;# A Programmable Editor Gavin Holt
; Standing upon the shoulders of giants, developed borrowing from various scripts:
; -	HiEdit.dll		Antonis Kyprianou (akyprian)
; -	HiEdit.ahk		Miodrag Milic (majkinetor)
; -	HiEdit _test.ahk 	Magnetometer
; -	AHKPAd			Michael Peters
; -	QuickAHK		 (jballi)
; -	Vic	Editor		Normand Lamoureux (Normand)
;
;# Setup AHK Environment
#SingleInstance Off
#NoEnv
#NoTrayIcon
#MaxMem 128
SetWorkingDir, %A_ScriptDir%
AutoTrim,Off
SetBatchLines,-1
SetControlDelay,-1
SetWinDelay,-1
ListLines, Off
DetectHiddenWindows, On
SetTitleMatchMode,2
SendMode, Input
Process,Priority,,A
CoordMode, Mouse, Relative
Is there a way to achieve this behaviour in my compiled AHK application?

Kind Regards Gavin Holt
geek
Posts: 1053
Joined: 02 Oct 2013, 22:13
Location: GeekDude
Contact:

Re: GUI Application: Single instance to capture parameters on repeated launch

11 Apr 2023, 08:03

Typically, this is done by allowing multiple instances, and then making the first thing your code does is search for other instances. If another instance is found, you send it a custom Window Message that you catch with OnMessage, for example something based on WM_COPYDATA.

Alternatively, you could use ObjRegisterActive to make your primary instance expose a COM object to the system, allowing secondary instances to pull that object and use it to trigger any file loading. Doing that would allow for easy future development of plugins.

The world is your oyster, and your options extend far beyond these.
User avatar
Gavin
Posts: 12
Joined: 14 Jul 2020, 03:35

Re: GUI Application: Single instance to capture parameters on repeated launch

18 Apr 2023, 06:42

Hi

Within my complied code editor script, I have been trying this is stages:

1. Detect first launch.
2. Detect second launch and abort (so I don't lose my current invocation)

Code: Select all

;# Setup AHK Environment
#SingleInstance Off
#NoEnv
#NoTrayIcon
#MaxMem 128
SetWorkingDir, %A_ScriptDir%
AutoTrim,Off
SetBatchLines,-1
SetControlDelay,-1
SetWinDelay,-1
ListLines, Off
DetectHiddenWindows, On
SetTitleMatchMode,2
SendMode, Input
Process,Priority,,A
CoordMode, Mouse, Relative

$MySingleInstance()

; Lower down after autoexec section
$MySingleInstance() {
    If $FirstInstance() {
        msgbox "First instance"
    } else {
        msgbox "New instance"
        ExitApp
    }
}

$FirstInstance() {
    local FirstInstancePID
    Process, Exist, %A_ScriptName%
    FirstInstancePID := ErrorLevel
    if (FirstInstancePID = DllCall("GetCurrentProcessId"))
    {
        return, true
    } else {
        return, false
    }
}
This does not work, my running instance is replaced by the new instance - and any unsaved work in my editor is lost!

Any help welcome

Kind Regards Gavin Holt
User avatar
Gavin
Posts: 12
Joined: 14 Jul 2020, 03:35

Re: GUI Application: Single instance to capture parameters on repeated launch

02 May 2023, 17:20

Hi,

I am still struggling with this problem.

The approach above does not work to detect new instances of my compiled script:

- Repeated execution of APEditor.exe, from the same folder, simply restarts the editor - losing any unsaved work.
- Interestingly, if I make a copy of the compiled script in another folder, and execute that copy - the "New" instance is identified.

I haver had similar results with other methods to check if an instance is already running:

- https://www.autohotkey.com/board/topic/76240-single-instance-force-compiled-scripts-only/

- viewtopic.php?t=28667

My lovely customized editor is not much use if repeated executions effectively wipe out any open tabs with data loss!

- https://github.com/Gavin-Holt/APEditor

Any help welcome.

Kind Regards Gavin Holt

I am happily using old versions of AHK/AHK2EXE

- Ahk2Exe v1.0.48.05
- AutoHotkeySC.bin 25.09.2009
ananthuthilakan
Posts: 188
Joined: 08 Jul 2019, 05:37
Contact:

Re: GUI Application: Single instance to capture parameters on repeated launch

04 May 2023, 12:46

the most simplest approach

Code: Select all

#SingleInstance Off
#NoEnv
#NoTrayIcon
#MaxMem 128
SetWorkingDir, %A_ScriptDir%
AutoTrim,Off
SetBatchLines,-1
SetControlDelay,-1
SetWinDelay,-1
ListLines, Off
DetectHiddenWindows, On
SetTitleMatchMode,2
SendMode, Input
Process,Priority,,A
CoordMode, Mouse, Relative

iniRead,winid,windowid.ini,winid,winid

if winexist("testtitle ahk_id " . winid)
{
msgbox, already exist
WinActivate,% "testtitle ahk_id " . winid
Exitapp
}

gui, add, button ,, ok
gui, show , w400 h400 ,testtitle
WinGet,winid, ID, A ; getting window id immidiatly after showing window
iniwrite,%winid%,windowid.ini,winid,winid

return


GuiClose:
ExitApp
little more advanced approach to send message to 1st instance to show the gui of first instance if hidden or do other stuff based on the message you send

Code: Select all

#SingleInstance Off
#NoEnv
#NoTrayIcon
#MaxMem 128
SetWorkingDir, %A_ScriptDir%
AutoTrim,Off
SetBatchLines,-1
SetControlDelay,-1
SetWinDelay,-1
ListLines, Off
DetectHiddenWindows, On
SetTitleMatchMode,2
SendMode, Input
Process,Priority,,A
CoordMode, Mouse, Relative

iniRead,winid,windowid.ini,winid,winid
TargetScriptTitle := "testtitle ahk_id" . winid
StringToSend:="alreadyExist" ; just in case you want to send any data to 1st instance and do something based on that
result := Send_WM_COPYDATA(StringToSend, TargetScriptTitle)
if (result=1){
msgbox, already exist  `n it will show the already existing instance 
exitapp
}
OnMessage(0x004A, "Receive_WM_COPYDATA")



gui, add, button ,, ok
gui, show , w400 h400 ,testtitle
WinGet,winid, ID, A
iniwrite,%winid%,windowid.ini,winid,winid

return

showguitimer:
gui, show, x0 y0
return


GuiClose:
ExitApp


Receive_WM_COPYDATA(wParam, lParam)
{
    StringAddress := NumGet(lParam + 2*A_PtrSize)  ; Retrieves the CopyDataStruct's lpData member.
   Global firstinstance_message := StrGet(StringAddress)  ; Copy the string out of the 
   settimer,showguitimer, -2
    return true  ; Returning 1 (true) is the traditional way to acknowledge this message.
}

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.
}

User avatar
Gavin
Posts: 12
Joined: 14 Jul 2020, 03:35

Re: GUI Application: Single instance to capture parameters on repeated launch

07 May 2023, 15:10

Hi,

Many thanks for your reply.

I can compile and run the simple example (with my versions of AHK2exe and AutoHotkeySC.bin) and it detects any second instance.

However, once I add the code to my script, it fails to detect new instances (attached) !

Sorry, but I really can't work out why your functioning code does not work in my script.

Could this be something to do with the HiEdit control?

Kind Regards Gavin Holt

PS. The advanced example, and keep1stinstance.ahk, fail to compile with my old versions.
Attachments
APEditor.ahk
Updated with the simple code
(49.84 KiB) Downloaded 21 times
just me
Posts: 9528
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: GUI Application: Single instance to capture parameters on repeated launch

08 May 2023, 08:51

Code: Select all

#SingleInstance, Ignore
AppName := "APEditor"
DetectHiddenWindows, On
SetTitleMatchMode, Regex
If WinExist(AppName . "$ ahk_class AutoHotkeyGUI") ; AppName must occur at the end of the title ($)
   ExitApp
DetectHiddenWindows, ??? ; if reqired
SetTitleMatchMode, ??? ; if reqired
...
...
...
Gui, Show, w965 h680,  %AppName%
Maybe?
User avatar
Gavin
Posts: 12
Joined: 14 Jul 2020, 03:35

Re: GUI Application: Single instance to capture parameters on repeated launch

15 May 2023, 08:38

Hi

Many thanks to those who have helped.

Unfortunately, the version of AHK/AHK2EXE I am using is not going to let me solve this problem with code in my script. I am bound to this version as more modern versions are causing problems.

As a solution, I have chosen to create a "runner.exe" - using AHK of course:

Code: Select all

#SingleInstance Off
#NoTrayIcon
DetectHiddenWindows, on
SetTitleMatchMode,2

If WinExist("- APEditor")
{
    WinActivate
    Send !FO
    Sleep 800
    SendInput %1%
    Exitapp
}

If FileExist(A_Temp "\APEditor.exe")
{
    Run, %A_Temp%\APEditor.exe "%1%"
    ExitApp
}
My executable has to live in %temp% to avoid OneDrive security sweeps!

Once again, thanks for all the pointers.

Kind Regards Gavin Holt

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: SmithyZoomZoom and 160 guests