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 

Prevent 2nd instance of process from running.

 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Ask for Help
View previous topic :: View next topic  
Author Message
CannedCheese



Joined: 21 May 2008
Posts: 85

PostPosted: Tue Aug 12, 2008 11:08 pm    Post subject: Prevent 2nd instance of process from running. Reply with quote

I'm trying to stop Outlook from running multiple instances, which seems to happen quite frequently thru addons and microsoft's inability to code correctly. I'd like to set a timer to check every second if a 2nd instance of Outlook.exe is running-- and close it if found.

I'm pretty clueless about how to go about implementing something like this, as I've never used a DLLCall directly in my own code. Any ideas? My work is pretty much married to Outlook 2002 right now, so switching isn't currently an option.
Back to top
View user's profile Send private message
Serenity



Joined: 07 Nov 2004
Posts: 1276

PostPosted: Tue Aug 12, 2008 11:50 pm    Post subject: Reply with quote

You could use the Process, Exist command to get the PID. It seems to get the first instance every time I try it with autohotkey.exe, so it might be the same for all programs. Then you could get a list of processes with this script and parse the results for PID of Outlook that doesn't match the one obtained with Process, Exist. Close this instance with Process, Close.
_________________
"Anything worth doing is worth doing slowly." - Mae West
Back to top
View user's profile Send private message Visit poster's website
Serenity



Joined: 07 Nov 2004
Posts: 1276

PostPosted: Wed Aug 13, 2008 12:16 am    Post subject: Reply with quote

Try this:

Code:
OnExit, HandleExit

success := DllCall( "advapi32.dll\LookupPrivilegeValueA"
                  , "uint", 0
                  , "str", "SeDebugPrivilege"
                  , "int64*", luid_SeDebugPrivilege )
if ( ReportError( ErrorLevel or !success
            , "LookupPrivilegeValue: SeDebugPrivilege"
            , "success = " success ) )
   ExitApp

Process, Exist
pid_this := ErrorLevel

hp_this := DllCall( "OpenProcess"
                  , "uint", 0x400                                 ; PROCESS_QUERY_INFORMATION
                  , "int", false
                  , "uint", pid_this )
if ( ReportError( ErrorLevel or hp_this = 0
            , "OpenProcess: pid_this"
            , "hp_this = " hp_this ) )
   ExitApp

success := DllCall( "advapi32.dll\OpenProcessToken"
                  , "uint", hp_this
                  , "uint", 0x20                                 ; TOKEN_ADJUST_PRIVILEGES
                  , "uint*", ht_this )
if ( ReportError( ErrorLevel or !success
            , "OpenProcessToken: hp_this"
            , "success = " success ) )
   ExitApp

VarSetCapacity( token_info, 4+( 8+4 ), 0 )
   EncodeInteger( 1, 4, &token_info, 0 )
   EncodeInteger( luid_SeDebugPrivilege, 8, &token_info, 4 )
      EncodeInteger( 2, 4, &token_info, 12 )                           ; SE_PRIVILEGE_ENABLED

success := DllCall( "advapi32.dll\AdjustTokenPrivileges"
                  , "uint", ht_this
                  , "int", false
                  , "uint", &token_info
                  , "uint", 0
                  , "uint", 0
                  , "uint", 0 )
if ( ReportError( ErrorLevel or !success
            , "AdjustTokenPrivileges: ht_this; SeDebugPrivilege ~ SE_PRIVILEGE_ENABLED"
            , "success = " success ) )
   ExitApp

 
; get first instance pid
process, exist, outlook.exe
instance1 := errorlevel

gosub, fetch
settimer, fetch, 3000 ; check every 3 seconds for new instance
return

fetch:
total := EnumProcesses( pid_list )

loop, parse, pid_list, |
{
   this := GetModuleFileNameEx( A_LoopField ) ; full path
   splitpath, this, name
   if (name = "outlook.exe" && A_LoopField != instance1)
      process, close, ahk_pid %A_LoopField%     
}   
return


HandleExit:
   DllCall( "CloseHandle", "uint", ht_this )
   DllCall( "CloseHandle", "uint", hp_this )
ExitApp


EncodeInteger( p_value, p_size, p_address, p_offset )
{
   loop, %p_size%
      DllCall( "RtlFillMemory", "uint", p_address+p_offset+A_Index-1, "uint", 1, "uchar", p_value >> ( 8*( A_Index-1 ) ) )
}

ReportError( p_condition, p_title, p_extra )
{
   if p_condition
      MsgBox,
         ( LTrim
            [Error] %p_title%
            EL = %ErrorLevel%, LE = %A_LastError%
           
            %p_extra%
         )
   
   return, p_condition
}

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
}

GetRemoteCommandLine( p_pid_target )
{
   hp_target := DllCall( "OpenProcess"
                     , "uint", 0x10                              ; PROCESS_VM_READ
                     , "int", false
                     , "uint", p_pid_target )
   if ( ErrorLevel or hp_target = 0 )
   {
      result = < error: OpenProcess > EL = %ErrorLevel%, LE = %A_LastError%, hp_target = %hp_target%
      Gosub, return
   }

   hm_kernel32 := DllCall( "GetModuleHandle", "str", "kernel32.dll" )

   pGetCommandLineA := DllCall( "GetProcAddress", "uint", hm_kernel32, "str", "GetCommandLineA" )

   buffer_size = 6
   VarSetCapacity( buffer, buffer_size )

   success := DllCall( "ReadProcessMemory", "uint", hp_target, "uint", pGetCommandLineA, "uint", &buffer, "uint", buffer_size, "uint", 0 )
   if ( ErrorLevel or !success )
   {
      result = < error: ReadProcessMemory 1 > EL = %ErrorLevel%, LE = %A_LastError%, success = %success%
      Gosub, return
   }

   loop, 4
      ppCommandLine += ( ( *( &buffer+A_Index ) ) << ( 8*( A_Index-1 ) ) )
   
   buffer_size = 4
   VarSetCapacity( buffer, buffer_size, 0 )

   success := DllCall( "ReadProcessMemory", "uint", hp_target, "uint", ppCommandLine, "uint", &buffer, "uint", buffer_size, "uint", 0 )
   if ( ErrorLevel or !success )
   {
      result = < error: ReadProcessMemory 2 > EL = %ErrorLevel%, LE = %A_LastError%, success = %success%
      Gosub, return
   }

   loop, 4
      pCommandLine += ( ( *( &buffer+A_Index-1 ) ) << ( 8*( A_Index-1 ) ) )

   buffer_size = 32768
   VarSetCapacity( result, buffer_size, 1 )
   
   success := DllCall( "ReadProcessMemory", "uint", hp_target, "uint", pCommandLine, "uint", &result, "uint", buffer_size, "uint", 0 )
   if ( !success )
   {
      loop, %buffer_size%
      {
         success := DllCall( "ReadProcessMemory", "uint", hp_target, "uint", pCommandLine+A_Index-1, "uint", &result, "uint", 1, "uint", 0 )
         
         if ( !success or Asc( result ) = 0 )
         {
            buffer_size := A_Index
            break
         }
      }
      success := DllCall( "ReadProcessMemory", "uint", hp_target, "uint", pCommandLine, "uint", &result, "uint", buffer_size, "uint", 0 )
      if ( ErrorLevel or !success )
      {
         result = < error: ReadProcessMemory 3 > EL = %ErrorLevel%, LE = %A_LastError%, success = %success%
         Gosub, return
      }
   }

return:
   DllCall( "CloseHandle", "uint", hp_target )
   
   return, result
}

_________________
"Anything worth doing is worth doing slowly." - Mae West
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
Page 1 of 1

 
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