How do I check if an application is running without calling the timer every 10 seconds to check current processes. Can anyone offer a solution?
Printable View
How do I check if an application is running without calling the timer every 10 seconds to check current processes. Can anyone offer a solution?
There is no other way, because in order to check it has to have orders to check something..Timer is the only way buddy (unless you only want to fire the thing once..)
---
Actually..you could use a do loop and add some doevents inside and such..but it will use 50% computer usage
Lol, nah, I'm trying to avoid CPU time, I guess I'll stick to the timer. I guess that makes sense though. Thanks Remix.
yeah timers are very low cpu..stick with that
If it's your app, then it could write a file, kind of like a flag, and then delete the file when the app closes. If it's another program, maybe you could use a batch file that does the same thing.
Or a WH_SHELL hook might tell you, but then this is a VB forum isn't it :)
Reasons why not to use a Timer:
http://www.vbforums.com/showthread.p...60#post2081260
Your point?Quote:
Originally Posted by moeur
what would you use instead?Quote:
Originally Posted by Jacob Roman
You said that timers are inconsistent, slow, horrible, but you haven't said why. And also I hardly think that any of those reasons matter in a situation like this. But if it is possible to do it through a hook then I would not touch any form of loop or timer.Quote:
Originally Posted by Jacob Roman
You'd still need to check for the presence of that file.Quote:
Originally Posted by dglienna
Sometimes I wonder myself what my point is.Quote:
Your point?
By installing a system-wide WHSHELL hook you can get HSHELL_WINDOWCREATED notifications whenever a new window is created. Unfortunately this has to be done in C.
Oh wait! there is that fancy method of yours that allows us to create win32 dlls in VB. Why don't you whip up a little demo for this monkey?
OK, I will, but to run it, you will need to mess with your VB files a little, and to make it, I will need to know how on earth to install a WHSHELL hook, and what on earth to do with it :D I will search for information but since I have no idea how one works I can't promise anything ;)Quote:
Originally Posted by moeur
I'll give you the code, then you compile it into a win32 dll.
OK, here is the code.
Make sure that the ShellProce function is in a standard module and that
you export the other two subs.
If this works it will open a world of programming, good luck.
VB Code:
Option Explicit 'This code is meant to be compiled into a win32 dll Private Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" ( _ ByVal idHook As Long, _ ByVal lpfn As Long, _ ByVal hmod As Long, _ ByVal dwThreadId As Long _ ) As Long Private Declare Function UnhookWindowsHookEx Lib "user32" ( _ ByVal hHook As Long _ ) As Long Private Declare Function CallNextHookEx Lib "user32" ( _ ByVal hHook As Long, _ ByVal ncode As Long, _ ByVal wParam As Long, _ lParam As Any _ ) As Long Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _ Destination As Any, _ Source As Any, _ ByVal Length As Long _ ) Public Const WH_SHELL = 10 Public Const HSHELL_WINDOWCREATED = 1 Public Const HSHELL_WINDOWDESTROYED = 2 Public Const HSHELL_ACTIVATESHELLWINDOW = 3 Public Const HSHELL_APPCOMMAND = 12 '??? ' #if(WINVER >= 0x0400) NT 4.0 and above Public Const HSHELL_WINDOWACTIVATED = 4 Public Const HSHELL_GETMINRECT = 5 Public Const HSHELL_REDRAW = 6 Public Const HSHELL_TASKMAN = 7 Public Const HSHELL_LANGUAGE = 8 ' #if(_WIN32_WINNT >= 0x0500) Public Const HSHELL_ACCESSIBILITYSTATE = 11 Public Const ACCESS_STICKYKEYS = &H1 Public Const ACCESS_FILTERKEYS = &H2 Public Const ACCESS_MOUSEKEYS = &H3 Public Type RECT Left As Long Top As Long Right As Long Bottom As Long End Type Private hHook As Long Public IsHooked As Boolean Public Sub SetShellHook() If IsHooked Then MsgBox "Don't hook SHELL twice or you will be unable to unhook it." Else 'the following line installs a system-wide hook hHook = SetWindowsHookEx(WH_SHELL, AddressOf ShellProc, App.hInstance, 0) IsHooked = True End If End Sub Public Sub RemoveShellHook() Dim temp As Long temp = UnhookWindowsHookEx(hHook) IsHooked = False End Sub '*** This routine must be placed in a standard module so we can use the AddressOf operator *** Public Function ShellProc(ByVal uCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long Dim structWindowSize As RECT Select Case uCode Case HSHELL_ACTIVATESHELLWINDOW '*** This one tells us that a new window has been created *** Case HSHELL_WINDOWCREATED 'wParam == Handle to the created window Case HSHELL_WINDOWDESTROYED 'wParam == Handle to the destroyed window Case HSHELL_WINDOWACTIVATED 'wParam == Handle to the activated window 'lParam == The value is TRUE if the window is in full-screen mode, or FALSE otherwise Case HSHELL_GETMINRECT 'wParam == Handle to the minimized or maximized window 'lParam == Pointer to a RECT structure CopyMemory structWindowSize, lParam, Len(structWindowSize) Case HSHELL_REDRAW 'wParam == Handle to the redrawn window 'lParam == The value is TRUE if the window is flashing, or FALSE otherwise Case HSHELL_TASKMAN Case HSHELL_LANGUAGE 'wParam == Handle to the window 'lParam == Handle to a keyboard layout Case HSHELL_ACCESSIBILITYSTATE 'wParam == ACCESS_FILTERKEYS, ACCESS_MOUSEKEYS, or ACCESS_STICKYKEYS If wParam = ACCESS_FILTERKEYS Then ElseIf wParam = ACCESS_MOUSEKEYS Then ElseIf wParam = ACCESS_STICKYKEYS Then End If Case HSHELL_APPCOMMAND 'wParam == Windows 2000: Where the WM_APPCOMMAND message was originally sent 'lParam == application command corresponding to the input event End Select ShellProc = CallNextHookEx(hHook, uCode, wParam, lParam) End Function
I have yet to find out the real reasons why. They are probably slow because they are objects, simulating a loop and executing the code within it ever so many intervals. How it maintains low CPU usage, I can't tell ya. I have no idea what code MS put in there to do this. But if I knew, then I would know why they are so slow, inconsistant, inaccurate, and such.Quote:
Originally Posted by penagate
When I get home, I'm gonna do an experiment with multiple timers to see why they make it even worse. When I am done, Im gonna upload it. ;)
It's possible to make your own timer functions with GetTickcount and the Sleep API and a Date variable.
Just calling Sleep with a value of one millsec, from inside the delay loop, reduces the CPU use to almost nill.
The Problem is that it's damned hard to kill your program if the user exits while in one of those loops.
A VB Timer doesn't have that problem.
That's because you aren't suppose to be using the Sleep API to slow down loops. It halts your program and all of it's events for a number of milliseconds, even after using DoEvents. It's no wonder why you have a hard time closing your app. This project I uploaded is a managed loop locked at 60 FPS. ;)
The GetTickCount API is only 10 ms accurate, while the QueryPerformanceCounter and QueryPerformanceFrequency API's are 1 ms accurate.
Ah ha. That's why Timers get worse and worse the more you use. Let's say you have a Listbox and 4 timers, with the first 3 set at an interval of 1, and the 4th one set at an interval of 1000. Using this code:
VB Code:
Option Explicit Private Sub Timer1_Timer() List1.AddItem "1" List1.AddItem "1" List1.AddItem "1" End Sub Private Sub Timer2_Timer() List1.AddItem "2" List1.AddItem "2" List1.AddItem "2" End Sub Private Sub Timer3_Timer() List1.AddItem "3" List1.AddItem "3" List1.AddItem "3" End Sub Private Sub Timer4_Timer() Timer1.Enabled = False Timer2.Enabled = False Timer3.Enabled = False Timer4.Enabled = False End Sub
You will see that Timer1's code will fire off first, then Timer2, then Timer3, then back to Timer1, 2, 3, etc. But sometimes it'll end up skipping every now and then, so sometimes you end up with 1, 3, 1, 2, 3, 1, 2, 1, 2, 3, etc. I had it add 3 items each into the listbox because I wanted to see if the timers actually ran at the same time to interupt each other. Turns out that it has to execute ALL of the code one timer at a time before executing code in the next timer. So the other timers have to wait. It was an interesting learning experience there. :)
That's why I mentioned the Sleep API :)Quote:
Originally Posted by Jacob Roman
And I just have Sleep set to 1 ms, not many things will hit it in that time.
The problem with killing the app doesn't come from the Sleep API.
It happens when the user tries to exit the program and triggers an event.
The forms unload event will run, but then the code will return to the loop and then to the sub that called the loop.
That normally prevents the app from closing.
I'll have to check into QueryPerformanceCounter and QueryPerformanceFrequency, sounds good.
BTW, I looked at another of your posts with your Managed Loop.zip
You mentioned that it's not setup to handle DoEvents.
So what do you do when you DO need to handle user events during a delay?
It does use DoEvents, although I recommend an alternative to it since it's one of the worse functions ever written for VB. And read post #18 which stated this:
So don't use the Sleep API at all ;)Quote:
Originally Posted by Jacob Roman
And if you noticed in my code, I had my loop setup like this:
VB Code:
Running = True Do While Running ... Loop
And the Form_Unload statement having this:
VB Code:
Private Sub Form_Unload(Cancel As integer) Running = False 'Will end the loop Unload Me End End Sub
Well, judging by your title of 'DirectX God', I'm guessing your delay loops are for games where time/respnce is critical.
But I'm more likely to use them to halt a program and wait for a user to answer a question or hit a 'continue' button.
In which case I see nothing wrong with using Sleep.
And the 'Stops your app' aspect is exactly what lowers the CPU use.
Let's see if you are right. You're using XP I assume, is that correct? I'm using ME so I can't do this. Make a sample app. Put the Sleep API in the General declarations and in the Form_Activate event, make it Sleep 100000. While the app is frozen, check how much CPU is being used. Is it low or high?
I run everything from win95/win98 - WinNt4-WinXp.Quote:
Originally Posted by Jacob Roman
(Several comps with several partions)
My main comp is XP.
Your post raises a lot of Q's.
Why can't you do it on ME?
Why would you want a delay loop in the Form_Activate event?
For grins and giggles I tried it.
The CPU useage was between 0-4%
Most of that was going to IE and taskmanager.
So what was the point of the exercise?
I just downloaded and tried your Managed Loop app.
CPU usage 100%
I also noticed the 'End' statement in the unload event.
If you change your code in frmMain like this:
You'll get the same problem I mentioned.VB Code:
Private Sub Form_Activate() Main txtTest.Text = "Gotcha!" End Sub Private Sub Form_Unload(Cancel As Integer) Running = False Unload Me ' End End Sub
The End statement isn't recommended because it can cause memory leaks depending on what else is in your code.
I sometimes have to use the End statement if I use this type of delay.
Just make sure that ALL objects from all modules get unloaded first :)
Next I tried adding Sleep to your Public Sub Game_Loop()
I did have to set Sleep to 10 ms to get an effect.
It lowered the CPU usage to 42% with no noticeable effect on the frame rate.
BTW, Hiya eyeRmonkey
Didn't mean to take over your post :)
Don't worry about what Taskmanager is telling you the CPU usage is.Quote:
And the 'Stops your app' aspect is exactly what lowers the CPU use
If you have a loop with a DoEvents statement in it you'll see 100% CPU usage. All that means is that the CPU is spending time in your loop rather than the idle process. Your DoEvents allows other threads to grab CPU time when they need it.
Putting a sleep statement in your loop only puts it back into the idle process for the sleep time. Besides, putting Sleep 10 in your loop limits your loop times to > 10ms increments.
What do I do once I've compiled it? Don't I have to register the hook or something?Quote:
Originally Posted by moeur
So, you should now have two subs you can call from VB in the dll. so from your VB appwill set the hookVB Code:
Option Explicit Private Declare Sub SetShellHook Lib "MyDll.dll" () Private Declare Sub RemoveShellHook Lib "MyDll.dll" () Private Sub Form_Load() SetShellHook End Sub Private Sub Form_Unload(Cancel As Integer) RemoveShellHook End Sub
First you have to decided what to do when the message is received. I doubt if you could do something as simple as popup a MsgBox, but you could use sendmessage to send mouse clicks or keypresses back to your VB app.
What's the point of making it a standard DLL anyway? If the code is that simple then it could just be run from an EXE like a regular callback. Obviously I have missed something.
It's because we are setting up a system-wide hook (as opposed to a thread-specific hook).Quote:
What's the point of making it a standard DLL anyway?
System-wide hooks can intercept messages dispatched to all threads in the system, and the code for their filter functions must (in most cases) be placed inside a Win32 dll. This is because when a thread needs to call the filter function it needs to map the function into its own address space and this can only be done using a Win32 dll.
So we are really injecting our code into every running thread that can receive shell messages.
moeur I changed SetShellHook into a function that returns the hHook value. But when I call it (It is supposed to display a messagebox with the result) the MsgBox doesn't show up :confused:
When you previously used this method to create dlls, did you try to invoke a messagebox from inside the dll?
Anyway, make SetShellHook a function that returns a Long and retrun the value that way.
NoQuote:
Originally Posted by moeur
That's what I did. The MsgBox call was in the test EXE project. That's why I'm so confused why it didn't work. I also tried stripping all the code except the CallNextHookEx call from ShellProc. Still no luck.Quote:
Originally Posted by moeur
Here's the code in the exe:
VB Code:
Option Explicit Private Declare Function SetShellHook _ Lib "C:\Yudster\Development\Visual Basic 6\My Code Tests\WH_SHELL hook\ShellHook.dll" ( _ ByVal lpfnCallback As Long _ ) As Long Private Declare Function RemoveShellHook _ Lib "C:\Yudster\Development\Visual Basic 6\My Code Tests\WH_SHELL hook\ShellHook.dll" ( _ ) As Long ' Private Sub cmdHook_Click() MsgBox "Result: " & SetShellHook(AddressOf HookNotify) End Sub Private Sub cmdUnhook_Click() MsgBox "Result: " & RemoveShellHook End Sub
The RemoveShellHook call returns zero and the MsgBox displays. The other one doesn't. I also tried removing the parameter from SetShellHook (like you had it). That didn't produce a MsgBox either.
What is the code inside the dll SetHookFunction, any changes?
Also, you will not be able to make a Notify callback from the dll, so don't worry about passing AddressOf HookNotify. The reason is that when the filter function is called by the message system, it is called in another process which has another address space and so pointers to functions in the VB address space won't make sense.
There are other reasons too as pointed out in this thread
http://www.vbforums.com/showthread.php?t=327589.
Quote:
Originally Posted by moeur
VB Code:
Public Function SetShellHook() As Long If (IsHooked) Then MsgBox "Don't hook SHELL twice or you will be unable to unhook it." Else 'mlpfnCallback = plpfnCallback 'the following line installs a system-wide hook hHook = SetWindowsHookExA(WH_SHELL, AddressOf ShellProc, App.hInstance, 0) IsHooked = True SetShellHook = hHook End If End Function
Bugger didn't think of that. What are we supposed to do with the hook then once it is set up anyway?Quote:
Also, you will not be able to make a Notify callback from the dll, so don't worry about passing AddressOf HookNotify. The reason is that when the filter function is called by the message system, it is called in another process which has another address space and so pointers to functions in the VB address space won't make sense.
BTW was I supposed to export ShellProc as well?
try this function instead.
VB Code:
Public Function SetShellHook() As Long If (IsHooked) Then SetShellHook = hHook Else 'the following line installs a system-wide hook hHook = SetWindowsHookExA(WH_SHELL, AddressOf ShellProc, App.hInstance, 0) IsHooked = True SetShellHook = hHook End If End Function
No that is only useful inside the dllQuote:
BTW was I supposed to export ShellProc as well?
We can do one of two things:Quote:
What are we supposed to do with the hook then once it is set up anyway?
1. handle the message inside the dll.
2. pass data back to the VB App using a WM_COPYDATA message.
I found the issue, it was App.hInstance. Changing that to zero made the function work and the Msgbox was displayed correctly (But of course the hook wasn't set).
Because App is part of the VB runtime we can't use that. So we need another way of finding the instance handle, unless we can somehow link to the VB runtime through code.
I just solved this problem for someone else. Let me find it...