Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Run a program or switch to an already running instance


  • Please log in to reply
18 replies to this topic
deanhill1971
  • Members
  • 58 posts
  • Last active: Dec 17 2011 02:42 AM
  • Joined: 30 Sep 2005
Maybe someone has already created a function like the following, but it's hard to meaningfully search the forum for "run", "switch", etc. :)

The following function will run a program or switch to it if already running. It shows a tray tip showing whether a run or switch is being done.

Also listed are examples where I've defined a bunch of Windows+Letter keys to open my favorite programs. So I just hit Win+T to always get to Total Commander. I think it is very handy.

; ===========================================================================
; Run a program or switch to it if already running.
;    Target - Program to run. E.g. Calc.exe or C:\Progs\Bobo.exe
;    WinTitle - Optional title of the window to activate.  Programs like
;       MS Outlook might have multiple windows open (main window and email
;       windows).  This parm allows activating a specific window.
; ===========================================================================
RunOrActivate(Target, WinTitle = "")
{
	; Get the filename without a path
	SplitPath, Target, TargetNameOnly

	Process, Exist, %TargetNameOnly%
	If ErrorLevel > 0
		PID = %ErrorLevel%
	Else
		Run, %Target%, , , PID

	; At least one app (Seapine TestTrack wouldn't always become the active
	; window after using Run), so we always force a window activate.
	; Activate by title if given, otherwise use PID.
	If WinTitle <> 
	{
		SetTitleMatchMode, 2
		WinWait, %WinTitle%, , 3
		TrayTip, , Activating Window Title "%WinTitle%" (%TargetNameOnly%)
		WinActivate, %WinTitle%
	}
	Else
	{
		WinWait, ahk_pid %PID%, , 3
		TrayTip, , Activating PID %PID% (%TargetNameOnly%)
		WinActivate, ahk_pid %PID%
	}


	SetTimer, RunOrActivateTrayTipOff, 1500
}

; Turn off the tray tip
RunOrActivateTrayTipOff:
	SetTimer, RunOrActivateTrayTipOff, off
	TrayTip
Return




; Example uses...
#b::RunOrActivate("C:\Program Files\Seapine\TestTrack Pro\TestTrack Pro Client.exe")
#c::RunOrActivate("control panel")
#d::RunOrActivate("cmd.exe")
#g::RunOrActivate("regedit.exe")
#i::Run, iexplore.exe
#n::RunOrActivate("uedit32.exe")

; Outlook can have multiple child windows, so specify which window to activate
#o::RunOrActivate("C:\Program Files\Microsoft Office\OFFICE11\OUTLOOK.EXE", "Microsoft Outlook")

#p::RunOrActivate("C:\Program Files\Perforce\P4Win.exe")
#q::RunOrActivate("C:\Program Files\Microsoft Visual Studio\COMMON\MSDev98\Bin\MSDEV.EXE", "Microsoft Visual")
#t::RunOrActivate("C:\Program Files\totalcmd\totalcmd.exe")
#y::RunOrActivate("wmplayer.exe")
#-::RunOrActivate("mspaint.exe")
#=::RunOrActivate("calc.exe")


ahoover
  • Members
  • 3 posts
  • Last active: Feb 12 2009 05:31 PM
  • Joined: 12 Feb 2009
This is a great script. I ran into one little problem when I wanted to run or activate a specific file that is open. For example, when I am editing the Autohotkey.ahk file, and other scripts in notepad, I had trouble getting it to go to the correct script I wanted. So, I added another optional input variable for the parameters to open.

; ===========================================================================
; Run a program or switch to it if already running.
;    Target - Program to run. E.g. Calc.exe or C:\Progs\Bobo.exe
;    WinTitle - Optional title of the window to activate.  Programs like
;    MS Outlook might have multiple windows open (main window and email
;    windows).  This parm allows activating a specific window.
; ===========================================================================

RunOrActivate(Target, WinTitle = "", Parameters = "")
{
   ; Get the filename without a path
   SplitPath, Target, TargetNameOnly

   Process, Exist, %TargetNameOnly%
   If ErrorLevel > 0
      PID = %ErrorLevel%
   Else
      Run, %Target% "%Parameters%", , , PID

   ; At least one app (Seapine TestTrack wouldn't always become the active
   ; window after using Run), so we always force a window activate.
   ; Activate by title if given, otherwise use PID.
   If WinTitle <> 
   {
      SetTitleMatchMode, 2
      WinWait, %WinTitle%, , 3
      TrayTip, , Activating Window Title "%WinTitle%" (%TargetNameOnly%)
      WinActivate, %WinTitle%
   }
   Else
   {
      WinWait, ahk_pid %PID%, , 3
      TrayTip, , Activating PID %PID% (%TargetNameOnly%)
      WinActivate, ahk_pid %PID%
   }


   SetTimer, RunOrActivateTrayTipOff, 1
}

; Turn off the tray tip
RunOrActivateTrayTipOff:
   SetTimer, RunOrActivateTrayTipOff, off
   TrayTip
Return

;example to run or activate the specific script, "Autohotkey"
^!+a::RunorActivate("notepad.exe", "AutoHotkey", "C:\Documents and Settings\ahoover.autotool\My Documents\AutoHotkey.ahk")


Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
You don't have to turn off TrayTip: it disappears by itself at most after 30 sec.

s.newave
  • Members
  • 6 posts
  • Last active: Dec 31 2009 08:23 AM
  • Joined: 22 Sep 2007
Really great script although i am trying to add a feature whereby if the the window is active and focused and the hotkey is pressed again then another instance of that target is launched. For example sometimes i prefer to launch another firefox browser window instead of using the same one so i would hit the hotkey to activate/launch firefox and then hit it again to launch a second window etc.. Should be very simple although with ahk and cant get this to work:

; ===========================================================================
; Run a program or switch to it if already running.
;    Target - Program to run. E.g. Calc.exe or C:\Progs\Bobo.exe
;    WinTitle - Optional title of the window to activate.  Programs like
;    MS Outlook might have multiple windows open (main window and email
;    windows).  This parm allows activating a specific window.
; ===========================================================================

RunOrActivate(Target, WinTitle = "", Parameters = "")
{
   ; Get the filename without a path
   SplitPath, Target, TargetNameOnly
	 
    IfWinActive, %WinTitle%
     {
     Run %Target%
     Return
     }
	 
   Process, Exist, %TargetNameOnly%
   If ErrorLevel > 0
      PID = %ErrorLevel%
   Else
      Run, %Target% "%Parameters%", , , PID

   ; At least one app (Seapine TestTrack wouldn't always become the active
   ; window after using Run), so we always force a window activate.
   ; Activate by title if given, otherwise use PID.
   If WinTitle <>
   {
      SetTitleMatchMode, 2
      WinWait, %WinTitle%, , 3
      ;TrayTip, , Activating Window Title "%WinTitle%" (%TargetNameOnly%)
      WinActivate, %WinTitle%
   }
   Else
   {
      WinWait, ahk_pid %PID%, , 3
      ;TrayTip, , Activating PID %PID% (%TargetNameOnly%)
      WinActivate, ahk_pid %PID%
   }


   ;SetTimer, RunOrActivateTrayTipOff, 1
}

; Turn off the tray tip
RunOrActivateTrayTipOff:
   SetTimer, RunOrActivateTrayTipOff, off
   TrayTip
Return

;example to run or activate the specific script, "Autohotkey"
;^!+a::RunorActivate("notepad.exe", "AutoHotkey", "C:\Documents and Settings\ahoover.autotool\My Documents\AutoHotkey.ahk")
#;::RunOrActivate("C:\Program Files\Mozilla Firefox\firefox.exe", "Mozilla Firefox", "")

Any ideas?

greynite
  • Members
  • 40 posts
  • Last active: Jan 12 2011 03:28 PM
  • Joined: 17 May 2008
SetTitleMatchMode, 2

is your bugaboo. It's set down in line 15 or so -- set it instead before your IfWinActive

Cheers,
Shawn

s.newave
  • Members
  • 6 posts
  • Last active: Dec 31 2009 08:23 AM
  • Joined: 22 Sep 2007
That was it. Thx!!

sanitizer
  • Members
  • 8 posts
  • Last active: Sep 19 2009 09:59 AM
  • Joined: 25 Aug 2009
hi, i want to launch "my document" so i want to put like:

runoractivate(%A_MyDocuments%)

but it gives me error

Run, %Target% "Parameters%",,,PID

I don't want to use the long path because I thought on using on another computer.

Thanks

sanitizer
  • Members
  • 8 posts
  • Last active: Sep 19 2009 09:59 AM
  • Joined: 25 Aug 2009
nah nervermind...

i used

Run %A_MyDocuments%

instead.

widow
  • Guests
  • Last active:
  • Joined: --
I found this in my collection of assembler source's. Dont know if you want it
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;                                          1Run (1 IMPORT in compiled exe)     

;Assembled with MASM32.

;

.386

.model flat,stdcall

option casemap:none



 include \masm32\include\windows.inc

 include \masm32\macros\macros.asm

 INCX user32 , kernel32

 include genmacro.inc



sSEH STRUCT

	OrgEsp            DD ?

	OrgEbp            DD ?

	SaveEip           DD ?

sSEH ENDS



MIN_KERNEL_SEARCH_BASE      EQU 070000000h

MAX_API_STRING_LENGTH       EQU 150

MUTEX_ALL_ACCESS            EQU 1F0001h

CREATE_DEFAULT_ERROR_MODE   EQU 04000000h



.CONST

;szGetCommandLineA      DB "GetCommandLineA",0

szCreateProcessA         DB "CreateProcessA",0

szOpenMutexA             DB "OpenMutexA",0

szCreateMutexA           DB "CreateMutexA",0

szGetStartupInfoA        DB "GetStartupInfoA",0

szLoadLibrary            DB "LoadLibraryA",0

szGetProcAddress         DB "GetProcAddress",0

szExitProcess            DB "ExitProcess",0



szUser32                 DB "user32",0

szMessageBox             DB "MessageBoxA",0



.data

DATAFOR General Use

;_GetCommandLineA             DD NULL

_CreateProcessA              DD NULL

_OpenMutexA                  DD NULL

_CreateMutexA                DD NULL

_GetStartupInfoA             DD NULL

_LoadLibrary                 DD NULL

_GetProcAddress              DD NULL

_ExitProcess                 DD NULL

_MessageBox                  DD NULL



SEH                          sSEH   <NULL>

dwKernelBase                 DD NULL

dwUserBase                   DD NULL



paramCount                   DD NULL

paramPtr                     DD NULL

usageString     DB  "1RUN <applicationame> [application command line parameters]",10,0



.data?

RUNTIMEDATA for General Use

hInstance       DD      ?

commandLinePtr  LPSTR   ?



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

DATAFOR multiple instance blocking ;;;;;;;;;;;;;;;;;;

mutexAttributes SECURITY_ATTRIBUTES <sizeof SECURITY_ATTRIBUTES,NULL,TRUE>



;        CODE START              ;

.code

	; -- PEID SAYS: Ding Boy's PE-lock Phantasm v1.0 / v1.1  --

      @@: 

      db 055h,057h,056h,052h,051h,053h,066h,081h,0C3h,0EBh,002h,\    ; FAKE 'OEP'

         0EBh,0FCh,066h,081h,0C3h,0EBh,002h,0EBh,0FCh,\

         088h,088h,088h,088h,088h,088h                               ; {POP EAX}*6

      ret 4

      nops 5

main: 

	ASSUME FS : NOTHING

      PUSH [ESP]

	CALL GetKernelBase

	 OR   EAX, EAX

	 JZ   @B

	MOV  dwKernelBase, EAX



START_SEH RETURN_HOME           ; ---- START SEH FRAME ---



        ;---- Why not make it look like a normal prog? ----



@@: wcall GetCommandLineA

     mov commandLinePtr,EAX

SHUT_SEH                        ; ---- STOP SEH FRAME ---



    call splitCommandLine

    mov paramCount, eax

    push eax



CHKAPPDBG:                      ; --- (LAJM #1) ---

        mov     eax,fs:[30h]    ; pointer to PEB

        movzx   eax,byte ptr [eax+2h]

        or      al,al

        jz      @f

        RET

     mov  eax,dword ptr fs:[20h]          ; #2

     or   eax,eax

     jNz   @f

     



@@:  ;---- GET SOME KERNEL API ADDRESSES  -----

LOAD_UP_API szLoadLibrary,       _LoadLibrary,      dwKernelBase

LOAD_UP_API szGetProcAddress,    _GetProcAddress,   dwKernelBase

;LOAD_UP_API szGetCommandLineA,   _GetCommandLineA,  dwKernelBase

LOAD_UP_API szCreateProcessA,    _CreateProcessA,   dwKernelBase

LOAD_UP_API szOpenMutexA,        _OpenMutexA,       dwKernelBase

LOAD_UP_API szCreateMutexA,      _CreateMutexA,     dwKernelBase

LOAD_UP_API szGetStartupInfoA,   _GetStartupInfoA,  dwKernelBase

LOAD_UP_API szExitProcess,       _ExitProcess,      dwKernelBase



	;---- LOAD USER32.DLL ----

mycall _LoadLibrary,OFFSET szUser32

    OR EAX,EAX

    JZ   QUIT

    MOV  dwUserBase, EAX

	;---- GET SOME MORE API ADDRESSES ----

LOAD_UP_API szMessageBox,       _MessageBox,      dwUserBase

;____

    ;

    ; Check for previous instance.

    ;

   mycall _OpenMutexA, MUTEX_ALL_ACCESS,FALSE, commandLinePtr



    .if eax != NULL ;another instance is already running

        jmp endme

    .endif

    ;

    ; Create Mutex to let other One Run instances know you're already here.

    ;

   mycall _CreateMutexA, offset mutexAttributes, TRUE, commandLinePtr

    pop eax

    .if eax !=0

        mycall WinMain, hInstance,NULL,commandLinePtr, SW_SHOWDEFAULT

    .else

        szText LmTitle2,"1RUN USAGE!"

        mycall _MessageBox ,NULL,offset  usageString, OFFSET LmTitle2, MB_OK

    .endif

endme:

              xor eax,eax

QUIT: SHUT_SEH

RETURN_HOME: mycall _ExitProcess,NULL       ; LEAVE IT!

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:dword ;;;;;;;;

        RUNTIMEDATA for start up info ;;

        startUp STARTUPINFO <>



        RESUMECODE

        mycall _GetStartupInfoA, offset startUp



        RUNTIMEDATA for proc info ;;;;;;

        unusedProcInfo PROCESS_INFORMATION <>



        RESUMECODE

          mycall _CreateProcessA, NULL, paramPtr, NULL, NULL, TRUE, \

                         CREATE_DEFAULT_ERROR_MODE, NULL, NULL, offset startUp,\

                         offset unusedProcInfo

        .if eax==FALSE

          mycall _MessageBox ,NULL, OFFSET usageString, NULL, MB_OK \

                        or MB_APPLMODAL or MB_ICONWARNING

        .endif

        returnzero

WinMain endp

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

splitCommandLine: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

DATAFOR splitCommandLine

paramListPtr dd NULL

RESUMECODE

    push ebx

    push esi    

    xor edx,edx  ;clear parameter counter

    mov esi,commandLinePtr

   call skipSpacesAndTabs

     mov bl, ' '

    .if byte ptr [esi] == '"'

        mov bl,'"'

        inc esi

    .endif

    mov commandLinePtr, esi

   call findChar

    .if byte ptr [esi] == 0 

        jmp commandLineSplit

    .endif

     mov byte ptr [esi], 0

    inc esi

   call skipSpacesAndTabs

    .if byte ptr [esi] == 0

        jmp commandLineSplit

    .endif

     mov edx, 1

     mov paramPtr, esi

commandLineSplit:

pop esi

pop ebx

mov eax, edx

ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

skipSpacesAndTabs: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

        lodsb

        cmp al,' '

        je skipSpacesAndTabs

        cmp al, 9

        je skipSpacesAndTabs

    dec esi

ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

findChar: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    lodsb

    cmp al, 0

    je findCharDone

    cmp al, bl

    jne findChar

findCharDone:

    dec esi

    ret

INCLUDE KERN_SHIT.ASM

end main





  • Guests
  • Last active:
  • Joined: --
Can this be used to run batch files instead of exe programs as well?

Meetloaf
  • Members
  • 46 posts
  • Last active: Mar 05 2016 07:57 PM
  • Joined: 02 Jun 2008
I want to thank you for this GEM! It is especially useful when running older applications.

For me, it's MoffSoftCalculator, kept throwing me an error about an instance already running. I said to myself...I wonder if there's an AHK remedy for that?

...voila

Thanks again!

medusa
  • Guests
  • Last active:
  • Joined: --
Thanks for this script! It's very useful to me.

I'm brand new to auto hot key, so please forgive me if this question has already been answered.

I would like a modified version of this script that will switch between multiple open instances if the hotkey is pressed again. For example, suppose you have 2 firefox instances open. Pressing the hotkey once will switch to one of the instances, and pressing it again will switch to the next one. Does this exist, or is there an easy way to modify this script to do it?

comvox
  • Members
  • 143 posts
  • Last active: Jan 29 2017 06:53 AM
  • Joined: 20 May 2009

I would like a modified version of this script that will switch between multiple open instances if the hotkey is pressed again. For example, suppose you have 2 firefox instances open. Pressing the hotkey once will switch to one of the instances, and pressing it again will switch to the next one. Does this exist, or is there an easy way to modify this script to do it?


The WinActivateBottom command is made to order for this. It is described as

Same as WinActivate except that it activates the bottommost (least recently active) matching window rather than the topmost.

See http://www.autohotke...ivateBottom.htm.

For example, if you want to rotate between several different instances of wordpad, one could have something like the following somewhere in one's script (use the hotkey you want)

^!x::
If Instr(Title,"WordPad")>0
      WinActivateBottom, WordPad
Return

This type of thing could be integrated with the other code. One could have something like the following:

SetTitleMatchMode,2
^!x::
WinGetActiveTitle, Title

If Instr(Title,"WordPad")>0
      WinActivateBottom, WordPad
Else
      RunOrActivate("WordPad.exe","WordPad")
Return

; Then the coding for the RunOrActivate function, taken from the earlier postings.

RunOrActivate(Target, WinTitle = "") 
{ 
   ; Get the filename without a path 
   SplitPath, Target, TargetNameOnly 

   Process, Exist, %TargetNameOnly% 
   If ErrorLevel > 0 
      PID = %ErrorLevel% 
   Else 
      Run, %Target%, , , PID 

   ; At least one app (Seapine TestTrack wouldn't always become the active 
   ; window after using Run), so we always force a window activate. 
   ; Activate by title if given, otherwise use PID. 
   If WinTitle <> 
   { 
      SetTitleMatchMode, 2 
      WinWait, %WinTitle%, , 3 
      TrayTip, , Activating Window Title "%WinTitle%" (%TargetNameOnly%) 
      WinActivate, %WinTitle% 
   } 
   Else 
   { 
      WinWait, ahk_pid %PID%, , 3 
      TrayTip, , Activating PID %PID% (%TargetNameOnly%) 
      WinActivate, ahk_pid %PID% 
   } 


   SetTimer, RunOrActivateTrayTipOff, 1500 
} 

; Turn off the tray tip 
RunOrActivateTrayTipOff: 
   SetTimer, RunOrActivateTrayTipOff, off 
   TrayTip 
Return


medusa
  • Guests
  • Last active:
  • Joined: --
Thanks so much for the helpful suggestions! Thanks to your pointers I am figuring this out.

I have a couple questions I haven't sorted out yet:

1. When a program is running and shows an icon in the notification area but doesn't have a window, my script doesn't open up a window for it. (This is in Windows, in case that wasn't obvious.) For example, Skype and Truecrypt spend much of their time running without windows, just with notification icons. Is there a way to make my script open up a window in this case?

2. I would like some of my shortcuts to open or switch to a windows explorer window for a specific folder path. What do I need to learn to add this?

3. My script seems to break the default behavior of Windows Key-L, to lock the screen. I haven't set Win-L to be something else in my script; if I turn off autohotkey I get Win-L working to lock the screen again. Any suggestions?

Here's my modified code, which seems to mostly work. I made a change to do the switching based on the ClassID because using the PID alone doesn't work (when there are multiple processes of the same program running).
RunActivateOrSwitch(Target, WinTitle = "")
{
   ; Get the filename without a path
   SplitPath, Target, TargetNameOnly

   ; Process returns the PID of a matching process exists, or 0 otherwise
   Process, Exist, %TargetNameOnly%
   ; Get the PID and the class if the process is already running
   If ErrorLevel > 0
   {
      PID = %ErrorLevel%
      WinGetClass, ClassID, ahk_pid %PID%
   }
   ; Run the program if the process is not already running
   Else
      Run, %Target%, , , PID

   ; At least one app  wouldn't always become the active
   ; window after using Run, so we always force a window activate.
   ; Activate by title if given, otherwise use class ID. Activating by class ID 
   ; appears more robust for switching than using PID.
   If WinTitle <>
   {
      SetTitleMatchMode, 2
      WinWait, %WinTitle%, , 3
      IfWinActive, %WinTitle%
	WinActivateBottom, %WinTitle%
      Else
	WinActivate, %WinTitle%
   }
   Else
   {
      WinWait, ahk_class %ClassID%, , 3
      IfWinActive, ahk_class %ClassID%
           WinActivateBottom, ahk_class %ClassID%
      Else
	WinActivate, ahk_class %ClassID%
   }
}


medusa
  • Guests
  • Last active:
  • Joined: --
I still haven't figured out the answers to these questions I posted in January. If anyone has suggestions, I would love to hear them.