AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Close all programs running from...
Goto page Previous  1, 2, 3  Next
 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Ask for Help
View previous topic :: View next topic  
Author Message
corrupt



Joined: 29 Dec 2004
Posts: 2446

PostPosted: Wed Feb 22, 2006 4:44 am    Post subject: Reply with quote

I haven't done much testing of the functionality for closing the applications but this is an alternate method for selecting the drive that seems to work ok:

Code:

; original code by Serenity
; modified drive selection method
Gui, Add, Button, x22 y80 w75 h23 gCloseApps, OK
Gui, Add, Button, x103 y80 w75 h23 gGuiClose, Cancel
Gui, Add, Text, x14 y10 w180 h15 , Please choose the drive from the list:
Gui, Add, DropDownList, x16 y40 w170 h120 AltSubmit Choose1 vList1, 

SplashTextOn, 200, 60,, Please wait.`n Generating a list of drives on your system...


; first get the drive letter of "MyDrive":
driveget, list, list  ; all drives
stringlen, len, list

loop, %len%
{
  stringleft, drive, list, 1
  driveget, label, label, %drive%:
  GuiControl,,List1, %drive%:     %label%
  d%A_Index% := drive
  stringtrimleft, list, list, 1
}

If d1<>
  GuiControl,Choose, List1, 1
Gui, Show, h116 w200, Choose Drive
SplashTextOff
Return


GetModuleFileNameEx( p_pid )
{
   if A_OSVersion in WIN_95,WIN_98,WIN_ME
   {
      MsgBox, This Windows version (%A_OSVersion%) is not supported.
      return
   }

   /*
      #define PROCESS_VM_READ           (0x0010)
      #define PROCESS_QUERY_INFORMATION (0x0400)
   */
   h_process := DllCall( "OpenProcess", "uint", 0x10|0x400, "int", false, "uint", p_pid )
   if ( ErrorLevel or h_process = 0 )
   {
      MsgBox, [OpenProcess] failed
      return
   }
   
   name_size = 255
   VarSetCapacity( name, name_size )
   
   result := DllCall( "psapi.dll\GetModuleFileNameExA", "uint", h_process, "uint", 0, "str", name, "uint", name_size )
   if ( ErrorLevel or result = 0 )
      MsgBox, [GetModuleFileNameExA] failed
   
   DllCall( "CloseHandle", h_process )
   
   return, name
}


CloseApps:
GuiControlGet, List1
mydrive := d%List1% ":"

; now get list of running programs:

WS_EX_APPWINDOW = 0x40000
WS_EX_TOOLWINDOW = 0x80
GW_OWNER = 4

WinGet, list, List

loop, %list%
{
   wid := list%A_Index%
   WinGet, es, ExStyle, ahk_id %wid%
   if ( ( ! DllCall( "GetWindow", "uint", wid, "uint", GW_OWNER ) and ! ( es & WS_EX_TOOLWINDOW ) )
         or ( es & WS_EX_APPWINDOW ) )
   {
      WinGet, pid, PID, ahk_id %wid%
      name := GetModuleFileNameEx( pid )
       
                 
      ; use splitpath to obtain drive letter of each app:     
      SplitPath, name, , , , , Drive
     

      ; close the program if drive matches:
      if Drive = %mydrive%
        WinClose, ahk_pid %pid%
     
   }
}
MsgBox, Finished processing drive %mydrive%
GuiClose:
ExitApp


Edit: fixed a couple bugs in the code I posted that prevented apps from being closed.


Last edited by corrupt on Wed Feb 22, 2006 6:03 am; edited 4 times in total
Back to top
View user's profile Send private message Visit poster's website
Serenity



Joined: 08 Nov 2004
Posts: 1272

PostPosted: Wed Feb 22, 2006 5:01 am    Post subject: Reply with quote

selioneru wrote:
one thing though it doesn't include processes in the tray or hidden processes


I can confirm this. Currently AutoHotkey cannot get the list of all running processes. One workaround is to use PSList to obtain the list of running processes.
_________________
"Anything worth doing is worth doing slowly." - Mae West
Back to top
View user's profile Send private message Visit poster's website
corrupt



Joined: 29 Dec 2004
Posts: 2446

PostPosted: Wed Feb 22, 2006 5:21 am    Post subject: Reply with quote

@Serenity
Should
Code:
if Drive = mydrive

be
Code:
if Drive = %mydrive%:

in the code you posted?
Back to top
View user's profile Send private message Visit poster's website
Serenity



Joined: 08 Nov 2004
Posts: 1272

PostPosted: Wed Feb 22, 2006 5:37 am    Post subject: Reply with quote

corrupt wrote:
@Serenity
Should
Code:
if Drive = mydrive

be
Code:
if Drive = %mydrive%:

in the code you posted?


Thanks. I just tested it, it should be:
Code:
if Drive = %mydrive%


SplitPath returns the drive letter and colon. The variable mydrive shouldn't need the last colon if it was added earlier in the script:

Code:
if label = MyDrive ; specify the label of your drive here
    mydrive = %drive%:


This version uses the Task Manager to retrieve the list of all running processes. I've tested it and it works. :) I've removed some of the msgboxes from Shimanov's GetModuleFileNameEx function to prevent interruptions.

Code:
driveget, list, list ; get all drives on filesystem
stringlen, len, list

loop, %len%
{
  stringleft, drive, list, 1
  driveget, label, label, %drive%:
  if label = MYDRIVE ; specify the label of your drive here
    mydrive = %drive%:     

  stringtrimleft, list, list, 1
}


; Task Manager needs to be running for this to work, with the Processes tab selected
ControlGet, List, List, Col2, SysListView321, Windows Task Manager  ; get the pids

Loop, Parse, List, `n
{
  name := getmodulefilenameex(A_LoopField)

  ; use splitpath to obtain drive letter of each app:     
  SplitPath, name, , , , , Drive
 
  ; close the program if drive matches:
  if Drive = %mydrive%
    WinClose, ahk_pid %pid%
}
return


GetModuleFileNameEx( p_pid )
{
   if A_OSVersion in WIN_95,WIN_98,WIN_ME
   {
      MsgBox, This Windows version (%A_OSVersion%) is not supported.
      return
   }

   /*
      #define PROCESS_VM_READ           (0x0010)
      #define PROCESS_QUERY_INFORMATION (0x0400)
   */
   h_process := DllCall( "OpenProcess", "uint", 0x10|0x400, "int", false, "uint", p_pid )
   
   name_size = 255
   VarSetCapacity( name, name_size )
   
   result := DllCall( "psapi.dll\GetModuleFileNameExA", "uint", h_process, "uint", 0, "str", name, "uint", name_size )
   
   DllCall( "CloseHandle", h_process )
   
   return, name
}

_________________
"Anything worth doing is worth doing slowly." - Mae West
Back to top
View user's profile Send private message Visit poster's website
corrupt



Joined: 29 Dec 2004
Posts: 2446

PostPosted: Wed Feb 22, 2006 6:01 am    Post subject: Reply with quote

Serenity wrote:
The variable mydrive shouldn't need the last colon if it was added earlier in the script:

Code:
if label = MyDrive ; specify the label of your drive here
    mydrive = %drive%:

Good point. I'll change the code I posted for consistency.
Back to top
View user's profile Send private message Visit poster's website
Serenity



Joined: 08 Nov 2004
Posts: 1272

PostPosted: Wed Feb 22, 2006 6:56 am    Post subject: Reply with quote

I've written a parser for PSList to obtain only the pids of the running processes:

Code:
; Get list of running processes with PSList http://www.sysinternals.com/Utilities/PsList.html
RunWait %comspec% /c pslist -t >list.txt, , Hide
Loop, Read, list.txt
{
  if A_LoopReadLine not contains Russinovich,Sysinternals,Process,Name,Idle
  Loop, parse, A_LoopReadLine, %A_Space%
   {
     if A_LoopField !=
        count++
         if count = 2 ; pid column
         {
            MsgBox, %A_LoopField% ; pid
            count=
            break
         }   
   }
}


If you want to use PSList instead of the Task Manager, replace the section that uses Task Manager with this:

Code:
RunWait %comspec% /c pslist -t >list.txt, , Hide
Loop, Read, list.txt
{
  if A_LoopReadLine not contains Russinovich,Sysinternals,Process,Name,Idle
  Loop, parse, A_LoopReadLine, %A_Space%
   {
     if A_LoopField !=
        count++
         if count = 2 ; pid column
         {
           name := getmodulefilenameex(A_LoopField) ; MsgBox, %A_LoopField%
            
            ; use splitpath to obtain drive letter of each app:     
            SplitPath, name, , , , , Drive
            
            if Drive = %mydrive%
               WinClose, ahk_pid %pid%
               
            count=
            break
         }   
   }
}
return

_________________
"Anything worth doing is worth doing slowly." - Mae West
Back to top
View user's profile Send private message Visit poster's website
shimanov



Joined: 25 Sep 2005
Posts: 610

PostPosted: Wed Feb 22, 2006 7:37 am    Post subject: Reply with quote

Here is another piece of the puzzle:

note: EnumProcesses and GetModuleFileNameEx are available with Windows NT 4.0, 2000, XP, etc.

Code:
Gui, Add, ListView, x5 y5 w400 h200, PID|file name
Gui, Show, x50 y50, EnumProcesses experiment

total := EnumProcesses( pid_list )

loop, parse, pid_list, |
   LV_Add( "", A_LoopField, GetModuleFileNameEx( A_LoopField ) )

LV_ModifyCol( 1, "Integer Sort AutoHdr" )
LV_ModifyCol( 2, "AutoHdr" )
return

GuiClose:
ExitApp

EnumProcesses( byref r_pid_list )
{
   if A_OSVersion in WIN_95,WIN_98,WIN_ME
   {
      MsgBox, This Windows version (%A_OSVersion%) is not supported.
      return, false
   }
   
   pid_list_size := 4*1000
   VarSetCapacity( pid_list, pid_list_size )
   
   status := DllCall( "psapi.dll\EnumProcesses", "uint", &pid_list, "uint", pid_list_size, "uint*", pid_list_actual )
   if ( ErrorLevel or !status )
      return, false
      
   total := pid_list_actual//4

   r_pid_list=
   address := &pid_list
   loop, %total%
   {
      r_pid_list := r_pid_list "|" ( *( address )+( *( address+1 ) << 8 )+( *( address+2 ) << 16 )+( *( address+3 ) << 24 ) )
      address += 4
   }
   
   StringTrimLeft, r_pid_list, r_pid_list, 1
   
   return, total
}

GetModuleFileNameEx( p_pid )
{
   if A_OSVersion in WIN_95,WIN_98,WIN_ME
   {
      MsgBox, This Windows version (%A_OSVersion%) is not supported.
      return
   }

   h_process := DllCall( "OpenProcess", "uint", 0x10|0x400, "int", false, "uint", p_pid )
   if ( ErrorLevel or h_process = 0 )
      return
   
   name_size = 255
   VarSetCapacity( name, name_size )
   
   result := DllCall( "psapi.dll\GetModuleFileNameExA", "uint", h_process, "uint", 0, "str", name, "uint", name_size )
   
   DllCall( "CloseHandle", h_process )
   
   return, name
}
Back to top
View user's profile Send private message
Serenity



Joined: 08 Nov 2004
Posts: 1272

PostPosted: Wed Feb 22, 2006 7:51 am    Post subject: Reply with quote

Fantastic! Now we can get list of running processes without using the Task Manager or an external utility. :)
_________________
"Anything worth doing is worth doing slowly." - Mae West
Back to top
View user's profile Send private message Visit poster's website
corrupt



Joined: 29 Dec 2004
Posts: 2446

PostPosted: Wed Feb 22, 2006 8:40 am    Post subject: Reply with quote

Nice Smile . Here's an attempt at putting the pieces together so far:

Code:

; code by Serenity, shimanov
; pieced together and modified by corrupt
 
Gui, Add, Button, x22 y80 w75 h23 gCloseApps, OK
Gui, Add, Button, x103 y80 w75 h23 gGuiClose, Cancel
Gui, Add, Text, x14 y10 w180 h15 , Please choose the drive from the list:
Gui, Add, DropDownList, x16 y40 w170 h120 Choose1 vList1, 

SplashTextOn, 200, 60,, Please wait.`n Generating a list of drives on your system...
driveget, list, list  ; all drives
stringlen, len, list
loop, %len%
{
  stringleft, drive, list, 1
  If drive <> A
    driveget, label, label, %drive%:
  GuiControl,,List1, %drive%:     %label%
  stringtrimleft, list, list, 1
}
GuiControl,Choose, List1, 1
Gui, Show, h116 w200, Choose Drive
SplashTextOff
Return

CloseApps:
GuiControlGet, List1
stringleft, listres, List1, 2
mydrive := listres
total := EnumProcesses( pid_list )
loop, parse, pid_list, |
{
      lname := GetModuleFileNameEx( A_LoopField )
      If lname<>
      {                 
        ; use splitpath to obtain drive letter of each app:     
        SplitPath, lname, , , , , Drive

        ; close the program if drive matches:
        if Drive = %mydrive%
        {
          WinClose, ahk_pid %A_LoopField%
          Process, WaitClose, %A_LoopField%, 4
          If (ErrorLevel)
          {
            Process, Close, %A_LoopField%
            Process, WaitClose, %A_LoopField%, 4
            If (ErrorLevel)
              MsgBox, %lname% is not responding. `nPlease manually close this application
          }
        }
      }
}
MsgBox, Finished processing drive %mydrive%
GuiClose:
ExitApp

EnumProcesses( byref r_pid_list )
{
   if A_OSVersion in WIN_95,WIN_98,WIN_ME
   {
      MsgBox, This Windows version (%A_OSVersion%) is not supported.
      return, false
   }
   
   pid_list_size := 4*1000
   VarSetCapacity( pid_list, pid_list_size )
   
   status := DllCall( "psapi.dll\EnumProcesses", "uint", &pid_list, "uint", pid_list_size, "uint*", pid_list_actual )
   if ( ErrorLevel or !status )
      return, false
       
   total := pid_list_actual//4

   r_pid_list=
   address := &pid_list
   loop, %total%
   {
      r_pid_list := r_pid_list "|" ( *( address )+( *( address+1 ) << 8 )+( *( address+2 ) << 16 )+( *( address+3 ) << 24 ) )
      address += 4
   }
   
   StringTrimLeft, r_pid_list, r_pid_list, 1
   
   return, total
}

GetModuleFileNameEx( p_pid )
{
   if A_OSVersion in WIN_95,WIN_98,WIN_ME
   {
      MsgBox, This Windows version (%A_OSVersion%) is not supported.
      return
   }

   h_process := DllCall( "OpenProcess", "uint", 0x10|0x400, "int", false, "uint", p_pid )
   if ( ErrorLevel or h_process = 0 )
      return
   
   name_size = 255
   VarSetCapacity( name, name_size )
   
   result := DllCall( "psapi.dll\GetModuleFileNameExA", "uint", h_process, "uint", 0, "str", name, "uint", name_size )
   
   DllCall( "CloseHandle", h_process )
   
   return, name
}



Edit:
- removed label retrieval for A: drive to drastically speed up drive detection process.
- removed a few unnecessary variables
Back to top
View user's profile Send private message Visit poster's website
selioneru



Joined: 19 Feb 2006
Posts: 8

PostPosted: Wed Feb 22, 2006 11:49 pm    Post subject: Reply with quote

Thanks SO Much! this rocks! Bravo! verrry cool Smile Props to Serenity and corrupt!
Back to top
View user's profile Send private message
corrupt



Joined: 29 Dec 2004
Posts: 2446

PostPosted: Thu Feb 23, 2006 1:27 am    Post subject: Reply with quote

...and shimanov... Smile
Back to top
View user's profile Send private message Visit poster's website
Laszlo



Joined: 14 Feb 2005
Posts: 4517
Location: Boulder, CO

PostPosted: Thu Feb 23, 2006 1:50 am    Post subject: Reply with quote

There is one process I cannot close. Even the console command "kill -9" fails, with the error: Access is denied. I have to close it manually from the Task Manager. Is there an easy way to grant the script the right to kill or make the process mortal?
Back to top
View user's profile Send private message
corrupt



Joined: 29 Dec 2004
Posts: 2446

PostPosted: Thu Feb 23, 2006 2:07 am    Post subject: Reply with quote

Laszlo wrote:
There is one process I cannot close. Even the console command "kill -9" fails, with the error: Access is denied. I have to close it manually from the Task Manager. Is there an easy way to grant the script the right to kill or make the process mortal?

I'm not too sure... Maybe try using RunAs with kill using the Administrator account? Maybe there another process that has to be closed first?
Back to top
View user's profile Send private message Visit poster's website
Laszlo



Joined: 14 Feb 2005
Posts: 4517
Location: Boulder, CO

PostPosted: Thu Feb 23, 2006 4:33 am    Post subject: Reply with quote

I am administrator, but still I tried RunAs, without success. I think it is some security settings of that particular service, because from the highest authority (Task Manager) it can be killed with a mouse click on the End button (and confirm my killer intensions).
Back to top
View user's profile Send private message
PhiLho



Joined: 27 Dec 2005
Posts: 6723
Location: France (near Paris)

PostPosted: Thu Feb 23, 2006 2:01 pm    Post subject: Reply with quote

There is the PSKill utility from SysInternals, but I don't know if it is more potent than NT's kill...
_________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Ask for Help All times are GMT
Goto page Previous  1, 2, 3  Next
Page 2 of 3

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group