Results 1 to 11 of 11

Thread: Look for a program, if it's open, close it.

  1. #1

    Thread Starter
    Junior Member
    Join Date
    May 2007
    Posts
    26

    Look for a program, if it's open, close it.

    What the title says, really.

    I've looked at examples from pscode and here but haven't quite managed to do it.

    I would like to write a function or routine that would be called when a button is pressed.

    Ex. Button1 pressed -> check for program X. If program X is open, close it. If not, tell the user program is not open.

    Thanks in advance.

  2. #2
    Next Of Kin baja_yu's Avatar
    Join Date
    Aug 2002
    Location
    /dev/root
    Posts
    5,989

    Re: Look for a program, if it's open, close it.

    What have you done so far/tried? What did it do and what didn't work?

    You can find a lot of examples if you Search the forum (http://www.vbforums.com/search.php) for keywords like "kill process", "end process", "list running processes" etc.

  3. #3
    PowerPoster
    Join Date
    Jul 2006
    Location
    Maldon, Essex. UK
    Posts
    6,334

    Re: Look for a program, if it's open, close it.

    Why would you want to do this ?

  4. #4

    Thread Starter
    Junior Member
    Join Date
    May 2007
    Posts
    26

    Re: Look for a program, if it's open, close it.

    Doogle,

    I have streams from which I watch online TV. Instead of copying pasting the links, I've created (almost complete) a program from which I can launch whatever channel I like, and close the media player once I press the button for each channel.

    Thus, I would like to close the media player (referring to program "x") cleanly each time.
    Last edited by Arkim; Jan 2nd, 2011 at 12:46 PM.

  5. #5
    Fanatic Member FireXtol's Avatar
    Join Date
    Apr 2010
    Posts
    874

    Re: Look for a program, if it's open, close it.

    You'll need just two APIs, as I recall. FindWindow, to get the handle. SendMessage with WM_CLOSE, to send the message(WM_CLOSE) to the hWnd returned from the first API.

    Using those terms should get you many results when searching, if you want examples.

  6. #6

    Thread Starter
    Junior Member
    Join Date
    May 2007
    Posts
    26

    Re: Look for a program, if it's open, close it.

    This is what I have so far, and it works for the "Close program" button. If there are other ways of doing it better or a clean close of the program, please share.

    Module:
    Code:
    Option Explicit
    
    Private Declare Function Process32First Lib "kernel32" (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long
    Private Declare Function Process32Next Lib "kernel32" (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long
    Private Declare Function CloseHandle Lib "Kernel32.dll" (ByVal Handle As Long) As Long
    Private Declare Function OpenProcess Lib "Kernel32.dll" (ByVal dwDesiredAccessas As Long, ByVal bInheritHandle As Long, ByVal dwProcId As Long) As Long
    Private Declare Function EnumProcesses Lib "psapi.dll" (ByRef lpidProcess As Long, ByVal cb As Long, ByRef cbNeeded As Long) As Long
    Private Declare Function GetModuleFileNameExA Lib "psapi.dll" (ByVal hProcess As Long, ByVal hModule As Long, ByVal ModuleName As String, ByVal nSize As Long) As Long
    Private Declare Function EnumProcessModules Lib "psapi.dll" (ByVal hProcess As Long, ByRef lphModule As Long, ByVal cb As Long, ByRef cbNeeded As Long) As Long
    Private Declare Function CreateToolhelp32Snapshot Lib "kernel32" (ByVal dwFlags As Long, ByVal th32ProcessID As Long) As Long
    Private Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" (lpVersionInformation As OSVERSIONINFO) As Long
    Private Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long
    
    Private Type PROCESSENTRY32
      dwSize As Long
      cntUsage As Long
      th32ProcessID As Long
      th32DefaultHeapID As Long
      th32ModuleID As Long
      cntThreads As Long
      th32ParentProcessID As Long
      pcPriClassBase As Long
      dwFlags As Long
      szExeFile As String * 260
    End Type
    
    Private Type OSVERSIONINFO
      dwOSVersionInfoSize As Long
      dwMajorVersion As Long
      dwMinorVersion As Long
      dwBuildNumber As Long
      dwPlatformId As Long
      szCSDVersion As String * 128
    End Type
    
    Private Const PROCESS_TERMINATE = &H1
    Private Const VER_PLATFORM_WIN32_WINDOWS = 1
    Private Const PROCESS_QUERY_INFORMATION = 1024
    Private Const PROCESS_VM_READ = 16
    Private Const TH32CS_SNAPPROCESS = &H2
    
    Private Function CheckVersion() As Long
    Dim tOS As OSVERSIONINFO
      tOS.dwOSVersionInfoSize = Len(tOS)
      Call GetVersionEx(tOS)
      CheckVersion = tOS.dwPlatformId
    End Function
    
    Private Function GetEXEProcessID(ByVal sEXE As String) As Long
      Dim aPID() As Long
      Dim lProcesses As Long
      Dim lProcess As Long
      Dim lModule As Long
      Dim sName As String
      Dim iIndex As Integer
      Dim bCopied As Long
      Dim lSnapShot As Long
      Dim tPE As PROCESSENTRY32
      Dim bDone As Boolean
      
      If CheckVersion() = VER_PLATFORM_WIN32_WINDOWS Then
        'Windows 9x
        'Create a SnapShot of the Currently Running Processes
        lSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
        If lSnapShot < 0 Then Exit Function
        tPE.dwSize = Len(tPE)
        'Buffer the First Processes Info..
        bCopied = Process32First(lSnapShot, tPE)
        Do While bCopied
          'While there are Processes List them..
          sName = Left$(tPE.szExeFile, InStr(tPE.szExeFile, Chr(0)) - 1)
          sName = Mid(sName, InStrRev(sName, "\") + 1)
          If InStr(sName, Chr(0)) Then
            sName = Left(sName, InStr(sName, Chr(0)) - 1)
          End If
          bCopied = Process32Next(lSnapShot, tPE)
          If StrComp(sEXE, sName, vbTextCompare) = 0 Then
            GetEXEProcessID = tPE.th32ProcessID
            Exit Do
          End If
        Loop
        
      Else
        'Windows NT
        'The EnumProcesses Function doesn't indicate how many Process there are,
        'so you need to pass a large array and trim off the empty elements
        'as cbNeeded will return the no. of Processes copied.
        ReDim aPID(255)
        Call EnumProcesses(aPID(0), 1024, lProcesses)
        lProcesses = lProcesses / 4
        ReDim Preserve aPID(lProcesses)
        
        For iIndex = 0 To lProcesses - 1
          'Get the Process Handle, by Opening the Process
          lProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 0, aPID(iIndex))
          If lProcess Then
            'Just get the First Module, all we need is the Handle to get
            'the Filename..
            If EnumProcessModules(lProcess, lModule, 4, 0&) Then
              sName = Space(260)
              Call GetModuleFileNameExA(lProcess, lModule, sName, Len(sName))
              If InStr(sName, "\") > 0 Then
                sName = Mid(sName, InStrRev(sName, "\") + 1)
              End If
              If InStr(sName, Chr(0)) Then
                sName = Left(sName, InStr(sName, Chr(0)) - 1)
              End If
              If StrComp(sEXE, sName, vbTextCompare) = 0 Then
                GetEXEProcessID = aPID(iIndex)
                bDone = True
              End If
            End If
            'Close the Process Handle
            CloseHandle lProcess
            If bDone Then Exit For
          End If
        Next
      End If
    End Function
    
    Public Function TerminateEXE(ByVal sEXE As String) As Boolean
      Dim lPID As Long
      Dim lProcess As Long
      
      lPID = GetEXEProcessID(sEXE)
      If lPID = 0 Then Exit Function
      lProcess = OpenProcess(PROCESS_TERMINATE, 0, lPID)
      Call TerminateProcess(lProcess, 0&)
      Call CloseHandle(lProcess)
      
      TerminateEXE = True
    End Function
    Close button:
    Code:
    Private Sub Command5_Click()
    Dim blnRet As Boolean
       blnRet = TerminateEXE("vlc.exe")
       If Not blnRet Then
           MsgBox "VLC Player is not running.", vbInformation, "Error"
       End If
    End Sub
    How can I make it so that for each time I press a button, the program checks if program X is running, and if it is, closes it, then it continues to its normal function (which is to open a file)?

  7. #7
    Next Of Kin baja_yu's Avatar
    Join Date
    Aug 2002
    Location
    /dev/root
    Posts
    5,989

    Re: Look for a program, if it's open, close it.

    Plus, if you were the one that Shelled the process in the first place, you would already have the handle and then you just need the SendMessage API that FireXtol mentioned.

  8. #8

    Thread Starter
    Junior Member
    Join Date
    May 2007
    Posts
    26

    Re: Look for a program, if it's open, close it.

    I haven't shelled the process (the media player) yet.

    Another note, when I use the code I posted above, the program closes obviously, but the icon for the program remains in the bottom right hand corner. Would this still occur if I use the FindWindow and SendMessage with WM_Close API?
    Last edited by Arkim; Jan 2nd, 2011 at 01:19 PM.

  9. #9
    Next Of Kin baja_yu's Avatar
    Join Date
    Aug 2002
    Location
    /dev/root
    Posts
    5,989

    Re: Look for a program, if it's open, close it.

    It stays there because you are terminating it pretty violently. WM_Close should take care of that. When you do Shell the player you will have the hwnd so no need to list all running processes. Even if you don't, finding the handle using FindWindow as FireXtol suggested is a much better approach.

  10. #10

    Thread Starter
    Junior Member
    Join Date
    May 2007
    Posts
    26

    Re: Look for a program, if it's open, close it.

    Edit: Ok, I fixed the sendmessage problem. Do double check though incase I am missing something, or can improve on something.

    Alright, so I've scratched my previous method and am going with FindWindow and SendMessage WM_Close.

    Here's what I have so far. Everything works until I tried using the SendMessage WM_Close API.

    Code:
    Option Explicit
    Private Declare Function FINDWINDOW Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
    Private Const WM_CLOSE = &H10
    
    Private Sub Command5_Click()
    'check if VLC media player is open
    'if it is, close it. If not, tell me it's not open.
    Dim lVLCwindowhandle As Long
    Dim lVLCplaying As Long
    
    lVLCwindowhandle = FINDWINDOW("VLC media player", vbNullString)
    lVLCplaying = FindWindowEx(lVLCwindowhandle, 0&, "QWidget", vbNullString)
    
    If lVLCplaying Then
    SendMessage lVLCplaying, WM_CLOSE, vbNull, vbNull '<--- this is where the problem was, I had forgotten to write "vbNull" x2
    MsgBox "VLC has been closed.", vbInformation, "Error"
    Else
    MsgBox "VLC is not open.", vbInformation, "Info"
    End If
    End Sub
    Thanks in advance.
    Last edited by Arkim; Jan 2nd, 2011 at 03:17 PM.

  11. #11

    Thread Starter
    Junior Member
    Join Date
    May 2007
    Posts
    26

    Re: Look for a program, if it's open, close it.

    My next question is;

    How can I turn the above into a routine, so that I don't have to type that out for every "Play channel" button in my program?

    I would like to instead of typing all that out, call the routine to check if VLC is open, close it if necessary, and then continue to the normal function of the button, which will be to shell another file?

    Edit: Alright, I just made a silly mistake. I forgot that when I'm streaming something, the title of the media player changes to whatever is playing, thus rendering the button in my app useless.. How can I overcome this? I included the classname as well, which is "QWidget" according to a window grabber, but that's not working. The media player still keeps the "- VLC media player" title in the title, but that's after the name of the file/stream playing.

    Edit 2: Ok, now after trying again, without changing the code, it works. Strange. It seems to work on and off. Why could this be?

    *Edit 3: Alright, I found out what the actual problem is. When the media player is minimized, it cannot be closed by my program. However if it is open, even in the background, it will be closed. Whether a file/stream is playing is irrelevant. How can I fix this?
    Last edited by Arkim; Jan 2nd, 2011 at 04:52 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width