|
-
Jan 2nd, 2011, 12:10 PM
#1
Thread Starter
Junior Member
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.
-
Jan 2nd, 2011, 12:25 PM
#2
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.
-
Jan 2nd, 2011, 12:27 PM
#3
Re: Look for a program, if it's open, close it.
Why would you want to do this ?
-
Jan 2nd, 2011, 12:35 PM
#4
Thread Starter
Junior Member
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.
-
Jan 2nd, 2011, 12:58 PM
#5
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.
Software I use and highly recommend: Opera, Miranda IM, Peerblock, Winamp, Unlocker Assistant, JoyToKey, Virtual CloneDrive, Secunia PSI, ExplorerXP, GOM Player, Real Alternative, Quicktime Alternative,Sumatra PDF, and non-freeware: Photoshop and VB6( ).
My codebank: AllRGB, Rounded Rectangle(math), Binary Server, Buddy Paint, LoadPictureGDI+, System GUID/Volume Serial, HexToAsc, List all processes and their paths, quasiString matching
Strings(search, extraction, retrieval etc): Retrieve BBCode Link from HTML, RemoveBetween ()'s, strFindBetween(str1,str2), Insert text in HTML, HTML - GetSpanByID
-
Jan 2nd, 2011, 01:00 PM
#6
Thread Starter
Junior Member
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)?
-
Jan 2nd, 2011, 01:01 PM
#7
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.
-
Jan 2nd, 2011, 01:15 PM
#8
Thread Starter
Junior Member
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.
-
Jan 2nd, 2011, 01:23 PM
#9
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.
-
Jan 2nd, 2011, 02:53 PM
#10
Thread Starter
Junior Member
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.
-
Jan 2nd, 2011, 03:19 PM
#11
Thread Starter
Junior Member
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|