Page 1 of 1

Get the full path to running executable?

Posted: Sun May 04, 2025 6:29 pm
by Quin
Hi,
I'm certain this is super basic, in fact I think I've seen code to do it before, but the search function is super unhelpful here.
Whenthe user clicks the "New" menu item in my application, I want a new instance of my app to be launchd. What's the best way of getting the full path to the running executable for use with RunProgram()?
Thanks!

Re: Get the full path to running executable?

Posted: Sun May 04, 2025 6:33 pm
by Demivec
Quin wrote: Sun May 04, 2025 6:29 pm Hi,
I'm certain this is super basic, in fact I think I've seen code to do it before, but the search function is super unhelpful here.
Whenthe user clicks the "New" menu item in my application, I want a new instance of my app to be launchd. What's the best way of getting the full path to the running executable for use with RunProgram()?
Thanks!
ProgramFilename()
https://www.purebasic.com/documentation/process/programfilename.html

Re: Get the full path to running executable?

Posted: Sun May 04, 2025 7:32 pm
by Quin
I knew it! I looked in compiler directives, FileSystem, many places, but of course not process...
Thanks Demivec.

Re: Get the full path to running executable?

Posted: Sun May 04, 2025 7:38 pm
by RASHAD
Hi Quin
For Windows ?

Re: Get the full path to running executable?

Posted: Sun May 04, 2025 8:27 pm
by Quin
RASHAD wrote: Sun May 04, 2025 7:38 pm Hi Quin
For Windows ?
Hi Rashad,
Yes, Windows only at the moment. :)

Re: Get the full path to running executable?

Posted: Mon May 05, 2025 2:22 am
by RASHAD
Hi Quin
Simple approach
1- Let your exe check for a special file in Home directory
2- Let your exe wright it's full path to special file in Home directory
3- Next run read the full path and run it
Adapt that way for your needs

For Windows it checks if the running is service too and get the full path
Good luck

Code: Select all

Global FilePath$

Prototype.i GetModuleFileNameExW(hProcess.l,hModule.l,*lpFilename,nSize.i)
Prototype.i GetModuleFileNameExA(hProcess.l,hModule.l,*lpFilename,nSize.i)

Global GetModuleFileNameEx.GetModuleFileNameExW

Lib = OpenLibrary(#PB_Any,"psapi.dll")
If Lib
  Global GetModuleFileNameEx.GetModuleFileNameExW = GetFunction(Lib,"GetModuleFileNameExW")  
Else
  MessageRequester("Warning", "Can not load Psapi.dll" ,#MB_ICONWARNING)
  End  
EndIf

Procedure CheckRunningExe(Process$)
  Proc32.PROCESSENTRY32
  Proc32\dwSize = SizeOf(PROCESSENTRY32)   
  snap = CreateToolhelp32Snapshot_(#TH32CS_SNAPPROCESS, 0) 
  If Snap
    If Process32First_(snap, @Proc32)
      While Process32Next_(snap, @Proc32)
        ImageName$ = PeekS(@Proc32\szExeFile)
        If LCase(ImageName$) = Process$   ;Your exe file name here in lower case characters 
          FilePath$ = Space(1024)
          hProcess = OpenProcess_(#PROCESS_ALL_ACCESS, 0, Proc32\th32ProcessID)
          If hProcess
            GetModuleFileNameEx(hProcess, 0, @FilePath$, Len(FilePath$))
            CloseHandle_(hProcess)
          EndIf
          Break
        EndIf            
      Wend
    EndIf
    CloseHandle_(Snap)
  EndIf
EndProcedure

CheckRunningExe("explorer.exe")
If GetPathPart(FilePath$) <> ""
  Debug "It's not a service"
  Debug FilePath$
Else
  Debug "It's a service"
EndIf 

Re: Get the full path to running executable?

Posted: Mon May 05, 2025 3:41 am
by Quin
RASHAD,
With all do respect for your incvredible PureBasic skills, what benifit does this have over ProgramFilename() other than being able to tell you if it's a service or not?
(to be clear, it's okay if that's the only benifit. It's just unclear to me.)

Re: Get the full path to running executable?

Posted: Mon May 05, 2025 3:54 am
by RASHAD
Hi Quin
1- First run your program
2- Then CheckRunningExe("your program.exe name only")
3- You will get the full path name

Can you post only the statement RunPrograme()

Example :

Code: Select all


RunProgram("notepad.exe","","")

Global FilePath$

Prototype.i GetModuleFileNameExW(hProcess.l,hModule.l,*lpFilename,nSize.i)
Prototype.i GetModuleFileNameExA(hProcess.l,hModule.l,*lpFilename,nSize.i)

Global GetModuleFileNameEx.GetModuleFileNameExW

Lib = OpenLibrary(#PB_Any,"psapi.dll")
If Lib
  Global GetModuleFileNameEx.GetModuleFileNameExW = GetFunction(Lib,"GetModuleFileNameExW")  
Else
  MessageRequester("Warning", "Can not load Psapi.dll" ,#MB_ICONWARNING)
  End  
EndIf

Procedure CheckRunningExe(Process$)
  Proc32.PROCESSENTRY32
  Proc32\dwSize = SizeOf(PROCESSENTRY32)   
  snap = CreateToolhelp32Snapshot_(#TH32CS_SNAPPROCESS, 0) 
  If Snap
    If Process32First_(snap, @Proc32)
      While Process32Next_(snap, @Proc32)
        ImageName$ = PeekS(@Proc32\szExeFile)
        If LCase(ImageName$) = Process$   ;Your exe file name here in lower case characters 
          FilePath$ = Space(1024)
          hProcess = OpenProcess_(#PROCESS_ALL_ACCESS, 0, Proc32\th32ProcessID)
          If hProcess
            GetModuleFileNameEx(hProcess, 0, @FilePath$, Len(FilePath$))
            CloseHandle_(hProcess)
          EndIf
          Break
        EndIf            
      Wend
    EndIf
    CloseHandle_(Snap)
  EndIf
EndProcedure

CheckRunningExe("notepad.exe")
If GetPathPart(FilePath$) <> ""
  Debug "It's not a service"
  Debug FilePath$
Else
  Debug "It's a service"
EndIf 


Re: Get the full path to running executable?

Posted: Mon May 05, 2025 4:08 am
by Quin
Ah, I see, makes sense. Thanks for the great code!

Re: Get the full path to running executable?

Posted: Mon May 05, 2025 4:17 am
by BarryG
@Rashad: I tried modifying your code to show all running processes with their paths, but the code below doesn't show all paths. Any idea why?

Code: Select all

Prototype.i GetModuleFileNameExW(hProcess.l,hModule.l,*lpFilename,nSize.i)

Global GetModuleFileNameEx.GetModuleFileNameExW

Lib = OpenLibrary(#PB_Any,"psapi.dll")
If Lib
  Global GetModuleFileNameEx.GetModuleFileNameExW = GetFunction(Lib,"GetModuleFileNameExW")  
Else
  MessageRequester("Warning", "Can not load Psapi.dll" ,#MB_ICONWARNING)
  End  
EndIf

Procedure ShowAllProcesses()
  Proc32.PROCESSENTRY32
  Proc32\dwSize = SizeOf(PROCESSENTRY32)   
  snap = CreateToolhelp32Snapshot_(#TH32CS_SNAPPROCESS, 0) 
  If Snap
    If Process32First_(snap, @Proc32)
      While Process32Next_(snap, @Proc32)
        ImageName$ = PeekS(@Proc32\szExeFile)
        FilePath$ = Space(1024)
        hProcess = OpenProcess_(#PROCESS_ALL_ACCESS, 0, Proc32\th32ProcessID)
        If hProcess = 0
          Debug ImageName$ ; No path included. :(
        Else
          GetModuleFileNameEx(hProcess, 0, @FilePath$, Len(FilePath$))
          CloseHandle_(hProcess)
          Debug FilePath$
        EndIf
      Wend
    EndIf
    CloseHandle_(Snap)
  EndIf
EndProcedure

ShowAllProcesses()

Re: Get the full path to running executable?

Posted: Mon May 05, 2025 5:32 am
by RASHAD
Hi BarryG
I think you mean the Clocked application like Calc,Notepad ...etc

Code: Select all

Prototype DwmGetWindowAttribute_(hWnd,dwAttribute.l,*pvAttribute,cbAttribute.l)

Procedure EnumRunningWindows()
  Protected hWnd
  hWnd = FindWindow_(0, 0)
  Repeat
    hWnd = GetWindow_(hWnd, #GW_HWNDNEXT)
    If hWnd And IsWindowVisible_(hWnd) And GetWindowLongPtr_(hWnd, #GWL_HWNDPARENT) = 0
      Protected title${#MAX_PATH},class${#MAX_PATH}
      GetWindowText_(hWnd, @title$, #MAX_PATH)
      GetClassName_(hWnd,@class$,#MAX_PATH)
      If title$ <> "" And title$ <> "Start" And title$ <> "Program Manager" And class$ <> "ApplicationFrameWindow" And class$ <> "Windows.UI.Core.CoreWindow"
        Debug title$ + "   " + Str(hwnd)
      ElseIf class$ = "ApplicationFrameWindow" Or class$ = "Windows.UI.Core.CoreWindow"
        Define DwmGetWindowAttribute_.DwmGetWindowAttribute_
        #DWMWA_CLOAKED = 14
        DWMAPIDLL=OpenLibrary(#PB_Any,"DWMAPI.DLL")
        If DWMAPIDLL
          DwmGetWindowAttribute_=GetFunction(DWMAPIDLL,"DwmGetWindowAttribute")
          If DwmGetWindowAttribute_ And DwmGetWindowAttribute_(hWnd,#DWMWA_CLOAKED,@Cloaked,SizeOf(Cloaked)) = #S_OK
            If Cloaked=0
              vis=1
              Debug title$ + "   " + Str(hwnd) 
            EndIf
          EndIf
          CloseLibrary(DWMAPIDLL)
        EndIf
      EndIf
    EndIf
  Until hWnd = 0
  ProcedureReturn #False
EndProcedure

EnumRunningWindows()

Re: Get the full path to running executable?

Posted: Mon May 05, 2025 6:43 am
by BarryG
No, not windows. I want only the processes like you see in the "Details" tab of Task Manager. When you run the code I posted, not all processes are shown with their paths; only some are. I'd like to see every process path like when you enable the "Image path name" column in Task Manager to see where the processes were run from.

Re: Get the full path to running executable?

Posted: Mon May 05, 2025 6:53 am
by RASHAD
Maybe

Code: Select all

Global PID,HDN,Name$
Global Dim HDname$(12)

#ProcessImageFileName = 27
#PROCESS_QUERY_LIMITED_INFORMATION = $1000

Procedure.s GetPathFromPID(PID)
  
  *Memory = AllocateMemory(2*#MAX_PATH)
  If *Memory
    HProcess = OpenProcess_(#PROCESS_QUERY_LIMITED_INFORMATION ,0,PID)
    If HProcess
      If ZwQueryInformationProcess_(HProcess ,#ProcessImageFileName,*Memory,2*#MAX_PATH,0) = 0
        Name$ = PeekS(*Memory,2*#MAX_PATH,#PB_Unicode)
        For i = 1 To 3
          Position = FindString(Name$,"\",Position+1)
        Next
        If Position
          Name$ = Right(Name$,Len(Name$)-Position)
        EndIf
        For x = 0 To HDN
          Name2$ = HDname$(x)+Name$
          If FileSize(Name2$) > 0
            Debug Name2$                
            Break
          EndIf
        Next
      EndIf
      CloseHandle_(HProcess)
    EndIf
    FreeMemory(*Memory)
  EndIf
  ProcedureReturn Name$
EndProcedure

Procedure.b CheckRunningExe()
  Proc32.PROCESSENTRY32
  Proc32\dwSize = SizeOf(PROCESSENTRY32)
  
  snap = CreateToolhelp32Snapshot_(#TH32CS_SNAPPROCESS, 0) 
  If snap
    If Process32First_(snap, @Proc32)
      While Process32Next_(snap, @Proc32)
        ;If GetExtensionPart(PeekS(@Proc32\szExeFile)) = "exe"
        PID = Proc32\th32ProcessID
        GetPathFromPID(PID)
        ;EndIf
      Wend
    EndIf
    CloseHandle_(snap) 
  EndIf 
  ProcedureReturn #False 
EndProcedure

Drives$ = Space(#MAX_PATH)
Result = GetLogicalDriveStrings_(#MAX_PATH,@Drives$)

For x = 0 To Result Step 4
  Type$ = PeekS(@Drives$+x,3)
  Result2 = GetDriveType_(Type$)
  If Result2 = #DRIVE_FIXED Or Result2 = #DRIVE_REMOTE Or Result2 = #DRIVE_RAMDISK
    HDname$(HDN) = Type$
    HDN+1
  EndIf
Next

CheckRunningExe() 

Re: Get the full path to running executable?

Posted: Mon May 05, 2025 6:57 am
by BarryG
Thanks, but that doesn't debug output anything at all. I will keep trying with my shorter snippet.

[Edit] Maybe it's not possible, because even this WMIC command doesn't list them all:

Code: Select all

wmic process get ProcessID,ExecutablePath