AutoHotkey Community

It is currently May 27th, 2012, 9:17 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 42 posts ]  Go to page Previous  1, 2, 3  Next
Author Message
 Post subject:
PostPosted: February 22nd, 2006, 4:44 am 
Offline
User avatar

Joined: December 29th, 2004, 1:28 pm
Posts: 2545
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 February 22nd, 2006, 6:03 am, edited 4 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 22nd, 2006, 5:01 am 
Offline

Joined: November 8th, 2004, 12:46 am
Posts: 1271
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
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 22nd, 2006, 5:21 am 
Offline
User avatar

Joined: December 29th, 2004, 1:28 pm
Posts: 2545
@Serenity
Should
Code:
if Drive = mydrive

be
Code:
if Drive = %mydrive%:

in the code you posted?


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 22nd, 2006, 5:37 am 
Offline

Joined: November 8th, 2004, 12:46 am
Posts: 1271
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
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 22nd, 2006, 6:01 am 
Offline
User avatar

Joined: December 29th, 2004, 1:28 pm
Posts: 2545
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 22nd, 2006, 6:56 am 
Offline

Joined: November 8th, 2004, 12:46 am
Posts: 1271
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
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 22nd, 2006, 7:37 am 
Offline

Joined: September 25th, 2005, 4:31 pm
Posts: 610
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
}


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 22nd, 2006, 7:51 am 
Offline

Joined: November 8th, 2004, 12:46 am
Posts: 1271
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
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 22nd, 2006, 8:40 am 
Offline
User avatar

Joined: December 29th, 2004, 1:28 pm
Posts: 2545
Nice :) . 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


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 22nd, 2006, 11:49 pm 
Offline

Joined: February 19th, 2006, 7:31 am
Posts: 8
Thanks SO Much! this rocks! Bravo! verrry cool :) Props to Serenity and corrupt!


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 23rd, 2006, 1:27 am 
Offline
User avatar

Joined: December 29th, 2004, 1:28 pm
Posts: 2545
...and shimanov... :)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 23rd, 2006, 1:50 am 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
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?


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 23rd, 2006, 2:07 am 
Offline
User avatar

Joined: December 29th, 2004, 1:28 pm
Posts: 2545
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?


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 23rd, 2006, 4:33 am 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
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).


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 23rd, 2006, 2:01 pm 
Offline

Joined: December 27th, 2005, 1:46 pm
Posts: 6837
Location: France (near Paris)
There is the PSKill utility from SysInternals, but I don't know if it is more potent than NT's kill...

_________________
Image vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 42 posts ]  Go to page Previous  1, 2, 3  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: BrandonHotkey, Google Feedfetcher, migz99 and 69 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group