Help with Singleinstance

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
elad770
Posts: 82
Joined: 30 Oct 2020, 16:21

Help with Singleinstance

Post by elad770 » 30 Oct 2020, 16:30

Hi everyone

I'm new to this website and I'm very happy to be here. Could be someone already addressed this somewhere but this place is like an ocean. Wasn't sure where to look

I have downloaded a program called Single instance. It has an ahk file and basically, it prevents a program I have in windows to open more than 1 instance. Which is great except for one thing:

After activating it, i lunch the 2nd instant but instead of closing the 1st instant, it is closing the instant I've just opened.

What i would like it to do is:

When opening the second event I would like for the FIRST event to close before the 2nd is loaded. I hope it's clear and i have attached the file. Thank you so much for helping
Attachments
SingleInstance.ahk
(6.43 KiB) Downloaded 43 times
Last edited by gregster on 30 Oct 2020, 16:32, edited 1 time in total.
Reason: Moved to 'Ask For Help'.
Rohwedder
Posts: 7551
Joined: 04 Jun 2014, 08:33
Location: Germany

Re: Help with Singleinstance

Post by Rohwedder » 31 Oct 2020, 01:52

Hallo,
this could only work if you don't open new programs yourself but let Autohotkey do it.
If you want to keep doing it yourself Autohotkey would need a time machine to close the previous instance of the program in the past.
elad770
Posts: 82
Joined: 30 Oct 2020, 16:21

Re: Help with Singleinstance

Post by elad770 » 31 Oct 2020, 18:12

The way it works is that I press a key to open a file with a program. When I press the second key I would like the program to immediately terminate and immediately open the new file.

Ok, let's do a time machine. I have no idea what that is and how to do one. Can you guide me step by step?

I'm willing to pay for anyone who can help out. This is fairly simple but I never used AutoHotkey and have no idea how to program it. However, I know exactly what I want to be happening and willing to show anyone who's interested to help

Thanks
elad770
Posts: 82
Joined: 30 Oct 2020, 16:21

Re: Help with Singleinstance

Post by elad770 » 31 Oct 2020, 18:24

I have and idea:

Let's say I have the command to open the file I want (a key For example)

What if I will assign the same key to close an open but the open will have a 0.5sec delay.

Will that work?
User avatar
boiler
Posts: 16767
Joined: 21 Dec 2014, 02:44

Re: Help with Singleinstance

Post by boiler » 31 Oct 2020, 20:18

If you’re using a key via script to open a file/app, you can have it close other instances of that file/app before opening the new one. At there doesn’t even need to be a 0.5 second delay or anything.

I think you misunderstood what Rohwedder was saying. He didn’t say you couldn’t close the original instance first if you’re opening it via a script. He was saying that if you’re opening the new instance yourself via Windows instead of a script, the script can’t know to close the first instance before the new instance starts to open.

I haven’t downloaded the SingleInstance script, but it doesn’t matter because instead of modifying that script, what you really want to do is write a new script that has hotkeys or buttons to launch programs from a pre-selected list of programs. That’s how it will know to close any existing instances first.
elad770
Posts: 82
Joined: 30 Oct 2020, 16:21

Re: Help with Singleinstance

Post by elad770 » 31 Oct 2020, 23:12

I highly appreciate your response Boiler.

Can you please teach me how to do that?

Here's the problem exactly because I'm not sure if I'm the one who's activating the file according to you:

I have an mp3 file. ---This file is triggered by a midi SysEx message (I use different software for that, I wish I could do it here)

After the program executes the file, I'm triggering another file with another command. The application opens a new instance and that creates a lot of problems for me.

I would like ONLY the last file that was open to being working. For that, I need a command that closes the application/window immediately and opens the new instance.

One other thing to add is that when I'm making a change to the mp3 file the program will stop and ask me if I want to save the file, so, I would like in this example for the script/command to wait until I answer that question.

If saving was not required - It should open immediately upon closing the last instance
If saving is required, the script will allow me to answer first and immediately after loading the new instance.

I will contribute 100$ to this amazing platform if someone can help me with the script or give me another solution on how to get it done
User avatar
boiler
Posts: 16767
Joined: 21 Dec 2014, 02:44

Re: Help with Singleinstance

Post by boiler » 01 Nov 2020, 07:24

What you are describing falls outside of what I outlined, which is you launching the new instance via a script, which would allow the script to know to close the other instances before opening the new one. Perhaps someone else knows how to capture the event of an app/file being opened in general and act on it. It would seem to be quite difficult if it’s even possible.

P.S. If you do find someone that is able to make a time machine for you, make sure to invest. ;)
User avatar
mikeyww
Posts: 26596
Joined: 09 Sep 2014, 18:38

Re: Help with Singleinstance

Post by mikeyww » 01 Nov 2020, 07:45

I'm not sure why this would be difficult with a minor modification to the script. The script is actually tracking the PIDs and the process names. Since each window has a unique ID or hWnd, you can do the following.

1. Get the hWnd and its process name. Store both in an associative array.

2. If the process name of interest already exists in the array, then close the hWnd from that old one, and remove that entry from the array.

I think that's about all that's needed.
User avatar
boiler
Posts: 16767
Joined: 21 Dec 2014, 02:44

Re: Help with Singleinstance

Post by boiler » 01 Nov 2020, 07:58

I'm not seeing how to accomplish the part highlighted below, but I'm interested to see how you do it.
elad770 wrote:
30 Oct 2020, 16:30
When opening the second event I would like for the FIRST event to close before the 2nd is loaded.
User avatar
mikeyww
Posts: 26596
Joined: 09 Sep 2014, 18:38

Re: Help with Singleinstance

Post by mikeyww » 01 Nov 2020, 08:08

You're right. I missed that part! If that is essential, your solution makes sense, @boiler.
elad770
Posts: 82
Joined: 30 Oct 2020, 16:21

Re: Help with Singleinstance

Post by elad770 » 01 Nov 2020, 12:50

Thank you so much mikeyww and boiler for your willingness to help. I now solved the main challenge you are having.

Now, I'm OK with the old instance to close AFTER the new one is open. Not a problem.

Again, let's back track and assume that the older instance will close immediately after the new one is open. Not a problem.

mikeyww, can you please revise the script for me or share it with me?

I need the new instance to activate and immediately the older instance to close.

Thank you so much
User avatar
mikeyww
Posts: 26596
Joined: 09 Sep 2014, 18:38

Re: Help with Singleinstance

Post by mikeyww » 01 Nov 2020, 14:51

Code: Select all

Global closeOldProcs := "notepad,iexplore" ; List of comma-separated process names to track (omit file extension)
Global handle := {}
Loop, parse, closeOldProcs, `,
{
 WinGet, win, List, % "ahk_exe " A_LoopField ".exe" ; Get all HWND for this process
 handle[A_LoopField] := win ? win1 : handle[A_LoopField] ; Store the first HWND for this process
}
; Detect newly created windows
; https://autohotkey.com/board/topic/80644-how-to-hook-on-to-shell-to-receive-its-messages/
Gui, +LastFound
hWnd := WinExist(), DllCall( "RegisterShellHookWindow", UInt,hWnd )
MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" )
OnMessage( MsgNum, "ShellMessage" )
Return

ShellMessage(wParam, lParam) { ; wParam = message number; lParam = HWND
 If (wParam != 1) ; 1 = Window was created
  Return
 ; A window was created
 WinGet, pname, ProcessName, % "ahk_id " lParam ; Get the new window's process name
 shortName := StrReplace(pname, ".exe") ; Get the process name without extension
 If shortName not in %closeOldProcs% ; Process is not of interest
  Return
 oldWin := "ahk_id " handle[shortName] ; Window title of the older instance
 If WinExist(oldWin) { ; Process of interest already exists as a window
  SoundBeep, 1500, 30
  MsgBox, 36, % Format("{:T}", shortName), Close the old window? ; Optional prompt
  IfMsgBox, No
   Return
  WinClose, %oldWin%
 }
 handle[shortName] := lParam ; Save the HWND
}
elad770
Posts: 82
Joined: 30 Oct 2020, 16:21

Re: Help with Singleinstance

Post by elad770 » 01 Nov 2020, 15:45

I can not describe how appreciative I am.
Thank you

I will test it tonight.

I just wanted to clarify few things.

1. Is this script in addition to the current or replaces it?

Second question:
2.the original program came with the Ahk file (which I'm assuming is where I place your script) and a text file that I could open an specified the programs path. Do I still use that as normal?
In other words , is your script only replaces the Ahk file?

Thank you in advance
User avatar
mikeyww
Posts: 26596
Joined: 09 Sep 2014, 18:38

Re: Help with Singleinstance

Post by mikeyww » 01 Nov 2020, 15:50

This is a standalone script and requires no other scripts or files. You just have to specify the processes of interest at the top.

It won't work with everything: works on windows, not tray icons without windows. If you already have more than one instance open, it won't close all of them. You would have to make adjustments to do that.

It's fairly simple in what it does: stores the most recent window handle of processes of interest. When it finds a new window of the same process, it uses the old handle to close the old window, and then saves the new handle. That's it.

Good luck!
elad770
Posts: 82
Joined: 30 Oct 2020, 16:21

Re: Help with Singleinstance

Post by elad770 » 01 Nov 2020, 22:58

You are amazing Mikey!!!

I ran the script and it does close the old window. There's only one tiny problem. It's asking me if I want to close the old window? I don't want to be asked if I want to close it or not

I want the window to close without asking me a question.

When I said that I want to reply before closing I was referring to the program itself. I was saying that if a file was changed the Program (running in the window) will ask if I want to save the changes or not. All I wanted to make sure is that
the script will not alter this behavior. (As opposed to "terminate" program that will occur from the task manager). But since the second instance is opened regardless either way, I would like to ask one final thing: if you can please remove the question that the script is asking and simply close the window.

Really looking forward to making it work :)
User avatar
mikeyww
Posts: 26596
Joined: 09 Sep 2014, 18:38

Re: Help with Singleinstance

Post by mikeyww » 01 Nov 2020, 23:03

I'm glad that it works. You can simply remove the optional prompt (noted as such) and the two lines that follow it. I believe that WinClose would then prompt you to save any unsaved work before the window closes (but I can't promise that).

The version below should work for you.

Code: Select all

Global closeOldProcs := "notepad,iexplore" ; List of comma-separated process names to track (omit file extension)
Global handle := {}, prompt := False
Loop, parse, closeOldProcs, `,
{
 WinGet, win, List, % "ahk_exe " A_LoopField ".exe" ; Get all HWND for this process
 handle[A_LoopField] := win ? win1 : handle[A_LoopField] ; Store the first HWND for this process
}
; Detect newly created windows
; https://autohotkey.com/board/topic/80644-how-to-hook-on-to-shell-to-receive-its-messages/
Gui, +LastFound
hWnd := WinExist(), DllCall( "RegisterShellHookWindow", UInt,hWnd )
MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" )
OnMessage( MsgNum, "ShellMessage" )
Return

ShellMessage(wParam, lParam) { ; wParam = message number; lParam = HWND
 If (wParam != 1) ; 1 = Window was created
  Return
 ; A window was created
 WinGet, pname, ProcessName, % "ahk_id " lParam ; Get the new window's process name
 shortName := StrReplace(pname, ".exe") ; Get the process name without extension
 If shortName not in %closeOldProcs% ; Process is not of interest
  Return
 oldWin := "ahk_id " handle[shortName] ; Window title of the older instance
 If WinExist(oldWin) { ; Process of interest already exists as a window
  SoundBeep, 1500, 30
  If prompt {
   MsgBox, 36, % Format("{:T}", shortName), Close the old window? ; Optional prompt
   IfMsgBox, No
    Return
  }
  WinClose, %oldWin%
 }
 handle[shortName] := lParam ; Save the HWND
}
elad770
Posts: 82
Joined: 30 Oct 2020, 16:21

Re: Help with Singleinstance

Post by elad770 » 01 Nov 2020, 23:07

I removed some lines but the whole function didn't work.

I'm probably removing something I shouldn't remove.

Can you be more specific? Or maybe reupload the script?
elad770
Posts: 82
Joined: 30 Oct 2020, 16:21

Re: Help with Singleinstance

Post by elad770 » 01 Nov 2020, 23:08

Silly me!

I didn't see that you already attached the revised version!

So sorry for that
elad770
Posts: 82
Joined: 30 Oct 2020, 16:21

Re: Help with Singleinstance

Post by elad770 » 01 Nov 2020, 23:24

Thank you so much, Mikey!

It worked flawlessly with no issues.

As promised, a 100$ donation was made to AutoHotkey to support the community and amazing people like you who love helping!
(I attached the donation confirmation)

Can I ask one last question?

I know there's a way to place a script in an exe file (like an installation file). So, when I use it on another computer or give it to someone they will simply install like they normally would and the script will be activated.

Can you please refer me to a video tutorial of how this can be done? Something that is easy to understand? I would highly appreciate it

Sincerely
Attachments
Capture_2020_11_01_23_18_13_925.png
Capture_2020_11_01_23_18_13_925.png (60.25 KiB) Viewed 880 times
User avatar
boiler
Posts: 16767
Joined: 21 Dec 2014, 02:44

Re: Help with Singleinstance

Post by boiler » 01 Nov 2020, 23:43

elad770 wrote: As promised, a 100$ donation was made to AutoHotkey to support the community
:bravo:

elad770 wrote: I know there's a way to place a script in an exe file (like an installation file). So, when I use it on another computer or give it to someone they will simply install like they normally would and the script will be activated.

Can you please refer me to a video tutorial of how this can be done? Something that is easy to understand? I would highly appreciate it
Just right-click on the script file in File Explorer and select "Compile Script". It will create the .exe version in the same directory, then others can run that file without having to install AHK. The .exe file isn't an installation file. It is the script itself in an executable format.
Post Reply

Return to “Ask for Help (v1)”