|
-
Aug 20th, 2012, 02:49 PM
#1
Thread Starter
Lively Member
AppActivate and FindWindow
I have used AppActivate in the past with VB6 Projects and am able to do same successfully in VB.Net.
When using AppActivate I just use AppActivate("My Form Name Here") and a Try/Catch Block
I reading some forums I see that there is a better way to do same in VB.Net using code similar to the following:
Question is - What do I use for lpszParentClass and lpszParentWindow?
I assume lpszParentWindow="My Form Name Here" - that's what I see in Task Manager 'Applications'
Code:
ParenthWnd = FindWindow(lpszParentClass, lpszParentWindow)
If ParenthWnd.Equals(IntPtr.Zero) Then
MsgBox("Program Not Running!")
Else
' Found it, so echo that we found it to debug window
' Then set it to foreground
MsgBox("Program Found")
SetForegroundWindow(ParenthWnd)
End If
-
Aug 20th, 2012, 03:57 PM
#2
Re: AppActivate and FindWindow
vb.net uses an entirely different protocol
Dim p As Process = Process.Start("notepad.exe")
You can then access a whole bunch of properties including p.MainWindowHandle although you shouldn't need API functions for most purposes.
-
Aug 20th, 2012, 04:21 PM
#3
Thread Starter
Lively Member
Re: AppActivate and FindWindow
Don't want to start a second instance of the program - just want to bring it to foreground if running or start the program if not running.
-
Aug 20th, 2012, 04:42 PM
#4
Re: AppActivate and FindWindow
Yes, I know. You use Process.Start instead of AppActivate and then you have access to all the properties you need. Bringing the process to the top is default behaviour using this method so that cuts out half the problem. If you want to wait for the program to be fully activated you use .WaitForInputIdle or check it's responding with .Responding
If you're going to use VB.Net, use it! It's not just a bigger version of VB6.
-
Aug 20th, 2012, 04:43 PM
#5
Re: AppActivate and FindWindow
Yes, I know. You use Process.Start instead of AppActivate and then you have access to all the properties you need. Bringing the process to the top is default behaviour using this method so that cuts out half the problem. If you want to wait for the program to be fully activated you use .WaitForInputIdle or check it's responding with .Responding
If you're going to use VB.Net, use it! It's not just a bigger version of VB6.
-
Aug 20th, 2012, 04:51 PM
#6
Thread Starter
Lively Member
Re: AppActivate and FindWindow
OK then please show me some code to set focus to an existing instance of MyProgram.exe or if it's not running then do Process.start("MyProgram.exe")
Thanks
-
Aug 20th, 2012, 06:02 PM
#7
Thread Starter
Lively Member
Re: AppActivate and FindWindow
OK then please show me some code to set focus to an existing instance of MyProgram.exe or if it's not running then do Process.start("MyProgram.exe")
Thanks
-
Aug 20th, 2012, 06:19 PM
#8
Re: AppActivate and FindWindow
vb.net Code:
Dim p As Process() = Process.GetProcessesByName("notepad")
If p.Length = 0 Then
Process.Start("notepad.exe")
End If
-
Aug 20th, 2012, 07:09 PM
#9
Re: AppActivate and FindWindow
Code:
Imports System.Runtime.InteropServices
Public Class Form1
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
Public Shared Function SetForegroundWindow(ByVal hWnd As IntPtr) As Boolean
End Function
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim hWnd As IntPtr = FindWindowByExe("notepad.exe")
If Not hWnd = IntPtr.Zero Then ' found
SetForegroundWindow(hWnd) ' bring to foreground
Else
Process.Start("notepad.exe")
End If
End Sub
Private Function FindWindowByExe(ByVal Filename As String) As IntPtr
Filename = System.IO.Path.GetFileNameWithoutExtension(Filename)
Dim procList() As Process = Process.GetProcesses
For Each p As Process In procList
If p.ProcessName.ToLower = Filename.ToLower Then
Return p.MainWindowHandle
End If
Next
Return IntPtr.Zero
End Function
End Class
-
Aug 20th, 2012, 09:56 PM
#10
Thread Starter
Lively Member
Re: AppActivate and FindWindow
Edgemeal:
Exactly what I was looking for. The FindWindowByExe was part I was missing.
Thanks.
Lee
-
Aug 25th, 2015, 03:19 AM
#11
Frenzied Member
Re: AppActivate and FindWindow
I have used this to invoke the calculator app (by replacing "notepad.exe" with "calc.exe"). It opens the calculator OK if it is not already open but if it is open and minimised, it doesn't maximise the window so to the user, it may appear that nothing is happening. I don't want to kill the process first either in case the user was doing something on the calculator previously. Is there a way to maximise the window if it is minimised?
-
Aug 25th, 2015, 07:12 AM
#12
Re: AppActivate and FindWindow
 Originally Posted by robertx
I have used this to invoke the calculator app (by replacing "notepad.exe" with "calc.exe"). It opens the calculator OK if it is not already open but if it is open and minimised, it doesn't maximise the window so to the user, it may appear that nothing is happening. I don't want to kill the process first either in case the user was doing something on the calculator previously. Is there a way to maximise the window if it is minimised?
IsIconic will tell you if window is minimized, ShowWindow will let you change windowstate.. could use GetProcessesByName to get handle also,..
Tested on Windows 7
Code:
Imports System.Runtime.InteropServices
Public Class Form1
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
Private Shared Function SetForegroundWindow(ByVal hWnd As IntPtr) As Boolean
End Function
Private Declare Auto Function IsIconic Lib "user32.dll" (ByVal hwnd As IntPtr) As Boolean
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function ShowWindow(ByVal hwnd As IntPtr, ByVal nCmdShow As Int32) As Boolean
End Function
Public Enum ShowWindowCommands As Integer
'for info on these commands see, http://msdn.microsoft.com/en-us/library/windows/desktop/ms633548%28v=vs.85%29.aspx
SW_HIDE = 0
SW_SHOWNORMAL = 1
SW_NORMAL = 1
SW_SHOWMINIMIZED = 2
SW_SHOWMAXIMIZED = 3
SW_MAXIMIZE = 3
SW_SHOWNOACTIVATE = 4
SW_SHOW = 5
SW_MINIMIZE = 6
SW_SHOWMINNOACTIVE = 7
SW_SHOWNA = 8 'similar to SW_SHOW, except the window is not activated.
SW_RESTORE = 9
SW_SHOWDEFAULT = 10
SW_FORCEMINIMIZE = 11
End Enum
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim hWnd As IntPtr = GetWindowHandle("Calc.exe")
If Not hWnd = IntPtr.Zero Then ' found
' if minimized then restore.
If IsIconic(hWnd) Then
ShowWindow(hWnd, ShowWindowCommands.SW_RESTORE)
Else
' bring to foreground
SetForegroundWindow(hWnd)
End If
Else
Process.Start("calc.exe")
End If
End Sub
Private Function GetWindowHandle(processName As String) As IntPtr
processName = System.IO.Path.GetFileNameWithoutExtension(processName)
Dim p() = Process.GetProcessesByName(processName)
Return If(p.Length > 0, p(0).MainWindowHandle, IntPtr.Zero)
End Function
End Class
Last edited by Edgemeal; Aug 26th, 2015 at 11:31 AM.
Reason: Tested on Windows 7
-
Aug 25th, 2015, 06:27 PM
#13
Frenzied Member
Re: AppActivate and FindWindow
If the calculator is closed and I open it by clicking on Button1, it opens OK as I would expect. If I click on Button1 again, it sends the calculator into the background of my application. Again I would expect this. If I click on Button1 a third time, the calculator is not restored from the background to the foreground which gives the user that nothing is happening. If I open the calculator and minimise it, clicking on Button1 restores it OK. So the question is how do I bring the calculator to the foreground when it is in the background? SetForegroundWindow(hWnd) doesn't achieve this.
-
Aug 25th, 2015, 07:54 PM
#14
Re: AppActivate and FindWindow
 Originally Posted by robertx
If the calculator is closed and I open it by clicking on Button1, it opens OK as I would expect. If I click on Button1 again, it sends the calculator into the background of my application. Again I would expect this..
WAIT, WHAT? That shouldn't happen! When you press the button the second time then,.. as the button is pressed down your app gets focus, and then when you release the button the button's click event is raised and the code runs, the code now finds the calc running so it just sets it as foreground thru the API call.
If not then can only guess you have other things going on that may be forcing the form to get re-activated/focus.
-
Aug 25th, 2015, 11:50 PM
#15
Frenzied Member
Re: AppActivate and FindWindow
If I open the calculator and click on the button a second time, the calculator disappears on the mouse down part of the click. What might be causing this to happen?
-
Aug 26th, 2015, 06:56 AM
#16
Re: AppActivate and FindWindow
Are you actually clicking on the button yourself or have you automated the click? If you've automated the cilck the sequence of events may not be the same as EdgeMeal described in post 14.
The best argument against democracy is a five minute conversation with the average voter - Winston Churchill
Hadoop actually sounds more like the way they greet each other in Yorkshire - Inferrd
-
Aug 26th, 2015, 07:04 AM
#17
Frenzied Member
Re: AppActivate and FindWindow
 Originally Posted by FunkyDexter
Are you actually clicking on the button yourself or have you automated the click? If you've automated the cilck the sequence of events may not be the same as EdgeMeal described in post 14.
I am clicking on the button myself.
-
Aug 26th, 2015, 07:13 AM
#18
Re: AppActivate and FindWindow
Hmm, then I'm out of ideas. I would expect the behaviour Edgemeal described which would not have resulted in calc being sent to the back on the second click (or at least, it would have got to the back and then straight back to the front) so it does sound as if there's something else going on.
In post 13 you said "If I click on Button1 again, it sends the calculator into the background of my application. Again I would expect this." Why would you expect it to go to the background? Why wouldn't it get found and reset to the front as Edgemeal described? Is there something going on there you haven't told us about?
Other than that I can only suggest putting a breakpoint into the routine where you find the calculator and set it to the foreground. Watch what happens as you step through the code. Does it find the calculator? Does it actually make the call to SetForegroundWindow?
The best argument against democracy is a five minute conversation with the average voter - Winston Churchill
Hadoop actually sounds more like the way they greet each other in Yorkshire - Inferrd
-
Aug 26th, 2015, 10:34 AM
#19
Re: AppActivate and FindWindow
 Originally Posted by robertx
I am clicking on the button myself.
What OS ver?
FWIW, I tried it on Win10 and it couldn't find calc running, so using FindWindow instead to get the handle, Edit. getprocess was returning two different handles for mainwindow, I've seen that happen before, should have just stuck with FindWindow!
Last edited by Edgemeal; Aug 26th, 2015 at 11:34 AM.
-
Aug 26th, 2015, 10:48 AM
#20
Re: AppActivate and FindWindow
Heres a quick Windows 10 Desktop fix...
Code:
Dim hWnd = FindWindow("ApplicationFrameWindow", "Calculator")
If Not hWnd = IntPtr.Zero Then ' found
' if minimized then restore.
If IsIconic(hWnd) Then
ShowWindow(hWnd, ShowWindowCommands.SW_RESTORE)
Else 'bring to foreground
SetForegroundWindow(hWnd)
End If
Else
Process.Start("calc.exe")
End If
-
Aug 26th, 2015, 07:21 PM
#21
Frenzied Member
Re: AppActivate and FindWindow
 Originally Posted by FunkyDexter
In post 13 you said "If I click on Button1 again, it sends the calculator into the background of my application. Again I would expect this." Why would you expect it to go to the background? Why wouldn't it get found and reset to the front as Edgemeal described? Is there something going on there you haven't told us about?
My expectation is exactly that - that the button would temporarily gain focus.
 Originally Posted by FunkyDexter
Watch what happens as you step through the code. Does it find the calculator? Does it actually make the call to SetForegroundWindow?
When I step through the code, it parses as expected.
-
Aug 26th, 2015, 07:24 PM
#22
Frenzied Member
Re: AppActivate and FindWindow
 Originally Posted by Edgemeal
Heres a quick Windows 10 Desktop fix...
Code:
Dim hWnd = FindWindow("ApplicationFrameWindow", "Calculator")
If Not hWnd = IntPtr.Zero Then ' found
' if minimized then restore.
If IsIconic(hWnd) Then
ShowWindow(hWnd, ShowWindowCommands.SW_RESTORE)
Else 'bring to foreground
SetForegroundWindow(hWnd)
End If
Else
Process.Start("calc.exe")
End If
This resolved the issue. I added the declaration:
Code:
<System.Runtime.InteropServices.DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
Private Function FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
End Function
and replaced
Code:
Dim hWnd As IntPtr = GetWindowHandle("calc")
with
Code:
Dim hWnd As IntPtr = FindWindow("ApplicationFrameWindow", "Calculator")
Problem solved. I am running Win 7 Pro 64 bit.
-
Aug 26th, 2015, 08:12 PM
#23
Re: AppActivate and FindWindow
 Originally Posted by robertx
Code:
Dim hWnd As IntPtr = FindWindow("ApplicationFrameWindow", "Calculator")
Problem solved. I am running Win 7 Pro 64 bit.
Thats odd, under Win7 for "calc.exe" I get,
Window Text: Calculator
Window ClassName: CalcFrame
Whats really nuts is, in Windows 10 I launch "calc.exe" and the calculator runs, ok great, now I look at task manager and its shown as "calculator.exe" huh? Windows 10 changed the name of the exe on the fly? I searched for "calculator.exe" and it was not found, it found "calc.exe" in 6 or 7 places! Clean install Win10 Pro and VS2015, all up to date.
-
Aug 26th, 2015, 08:59 PM
#24
Frenzied Member
Re: AppActivate and FindWindow
Actually the problem is not resolved. I just realised that FindWindow is returning a zero value if the calculator app is already open and is therefore opening a new instance of the calculator with each button click.
-
Aug 26th, 2015, 09:59 PM
#25
Re: AppActivate and FindWindow
 Originally Posted by robertx
Actually the problem is not resolved. I just realised that FindWindow is returning a zero value if the calculator app is already open and is therefore opening a new instance of the calculator with each button click.
Ya because calculator's classname in Win7 is "CalcFrame",
so try, FindWindow("CalcFrame", "Calculator")
-
Aug 26th, 2015, 10:39 PM
#26
Frenzied Member
Re: AppActivate and FindWindow
 Originally Posted by Edgemeal
Ya because calculator's classname in Win7 is "CalcFrame",
so try, FindWindow("CalcFrame", "Calculator")
OK great that resolved it. Now to make it compatible with different versions of Windows, I have done the following:
Code:
Dim hWnd As IntPtr
If Convert.ToDecimal(Environment.OSVersion.Version.Major.ToString & "." & Environment.OSVersion.Version.Minor.ToString)> 6.1 Then
hWnd = FindWindow("ApplicationFrameWindow", "Calculator")
Else
hWnd = FindWindow("CalcFrame", "Calculator")
End If
Is this the correct logic? My Windows 10 version is showing as 6.2 as per above. I thought Windows 8 was version 6.2...
-
Aug 27th, 2015, 05:51 AM
#27
Frenzied Member
Re: AppActivate and FindWindow
I have discovered that if the following is added to the compatibility tag of the app.manifest file, Environment.OSVersion.Version.Major returns the correct value of 10 on Windows 10.
Code:
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
-
Aug 27th, 2015, 05:52 AM
#28
Frenzied Member
Re: AppActivate and FindWindow
 Originally Posted by Edgemeal
Ya because calculator's classname in Win7 is "CalcFrame",
so try, FindWindow("CalcFrame", "Calculator")
What is the calculator's class name on Windows 8 and 8.1? Where can you look this up? Been googling without success...
-
Aug 27th, 2015, 07:32 AM
#29
Re: AppActivate and FindWindow
 Originally Posted by Edgemeal
Whats really nuts is, in Windows 10 I launch "calc.exe" and the calculator runs, ok great, now I look at task manager and its shown as "calculator.exe"  huh? Windows 10 changed the name of the exe on the fly?  I searched for "calculator.exe" and it was not found, it found "calc.exe" in 6 or 7 places! Clean install Win10 Pro and VS2015, all up to date.
Windows 10 Calculator is one of those so called Modern UI Apps. I think the 32KB file "Calc.exe" is kept for backwards compatibility and is a wrapper (launcher) for "Calculator.exe" which is 3MB in size.
If you right click on Calculator.exe as shown in the Details Tab of the Task Manager, there should be an option to open its file location, which for me is a folder inside the hidden system folder "C:\Program Files\WindowsApps"
-
Aug 27th, 2015, 09:13 AM
#30
Re: AppActivate and FindWindow
 Originally Posted by Inferrd
Windows 10 Calculator is one of those so called Modern UI Apps. I think the 32KB file "Calc.exe" is kept for backwards compatibility and is a wrapper (launcher) for "Calculator.exe" which is 3MB in size.
If you right click on Calculator.exe as shown in the Details Tab of the Task Manager, there should be an option to open its file location, which for me is a folder inside the hidden system folder "C:\Program Files\WindowsApps"
Thanks for the info, that explains a lot
-
Aug 27th, 2015, 09:17 AM
#31
Re: AppActivate and FindWindow
 Originally Posted by robertx
What is the calculator's class name on Windows 8 and 8.1? Where can you look this up? Been googling without success...
You can use utility like SPY++ or similar.
Here is is a simple one, (made in VB10), you drag the arrow to a window and it will display some info (text, classname) and has copy button, its based on MSDN VB6 code .paul. converted to VB.NET here,, http://www.vbforums.com/showthread.php?776255
-
Aug 27th, 2015, 06:23 PM
#32
Frenzied Member
Re: AppActivate and FindWindow
 Originally Posted by Edgemeal
You can use utility like SPY++ or similar.
Here is is a simple one, (made in VB10), you drag the arrow to a window and it will display some info (text, classname) and has copy button, its based on MSDN VB6 code .paul. converted to VB.NET here,, http://www.vbforums.com/showthread.php?776255
Thanks nice app...
-
Aug 27th, 2015, 06:25 PM
#33
Frenzied Member
Re: AppActivate and FindWindow
 Originally Posted by Inferrd
Windows 10 Calculator is one of those so called Modern UI Apps. I think the 32KB file "Calc.exe" is kept for backwards compatibility and is a wrapper (launcher) for "Calculator.exe" which is 3MB in size.
If you right click on Calculator.exe as shown in the Details Tab of the Task Manager, there should be an option to open its file location, which for me is a folder inside the hidden system folder "C:\Program Files\WindowsApps"
So this new calculator app was introduced with Windows 10? Is the calculator app in Windows 8 and 8.1 the same as the calculator app in Windows 7? I don't have a Windows 8 or 8.1 machine to check it out...
-
Aug 29th, 2015, 09:22 AM
#34
Re: AppActivate and FindWindow
 Originally Posted by robertx
So this new calculator app was introduced with Windows 10? Is the calculator app in Windows 8 and 8.1 the same as the calculator app in Windows 7? I don't have a Windows 8 or 8.1 machine to check it out...
Windows 8 has a Desktop calculator (calc.exe) that is virtually the same as Windows 7's calc.exe.
Windows 8 also has a calculator that is a Modern UI App (numbers.exe). It does not run on the Desktop.
Windows 10's calculator (calculator.exe) is similar in concept to Windows 8's Modern UI Calculator App, but they apparently call them Universal Apps in Windows 10, and they do now run in a window on the Desktop.
-
Aug 29th, 2015, 09:40 AM
#35
Frenzied Member
Re: AppActivate and FindWindow
 Originally Posted by Inferrd
Windows 8 has a Desktop calculator (calc.exe) that is virtually the same as Windows 7's calc.exe.
Windows 8 also has a calculator that is a Modern UI App (numbers.exe). It does not run on the Desktop.
Windows 10's calculator (calculator.exe) is similar in concept to Windows 8's Modern UI Calculator App, but they apparently call them Universal Apps in Windows 10, and they do now run in a window on the Desktop.
 Originally Posted by Infe[QUOTE=Inferrd
Windows 8 has a Desktop calculator (calc.exe) that is virtually the same as Windows 7's calc.exe.
Windows 8 also has a calculator that is a Modern UI App (numbers.exe). It does not run on the Desktop.
Windows 10's calculator (calculator.exe) is similar in concept to Windows 8's Modern UI Calculator App, but they apparently call them Universal Apps in Windows 10, and they do now run in a window on the Desktop.
So my logic therefore should be:
Code:
Dim hWnd As IntPtr
If Convert.ToDecimal(Environment.OSVersion.Version.Major.ToString & "." & Environment.OSVersion.Version.Minor.ToString)>= 10 Then
hWnd = FindWindow("ApplicationFrameWindow", "Calculator")
Else
hWnd = FindWindow("CalcFrame", "Calculator")
End If
For this to work, the compatibility node of the app.manifest needs to be modified to incorporate support for Windows 10. Otherwise Windows 10 will be identified as OSVersion 6.2 rather than (the correct) 10 and the code for the older calculator app will be invoked.
-
Aug 29th, 2015, 11:07 AM
#36
Re: AppActivate and FindWindow
 Originally Posted by robertx
For this to work, the compatibility node of the app.manifest needs to be modified to incorporate support for Windows 10. Otherwise Windows 10 will be identified as OSVersion 6.2 rather than (the correct) 10 and the code for the older calculator app will be invoked.
Calling Windows APIs are so fast I would just look for both types are not worry about windows versions and setting manifests, etc..., something like...
Code:
' find a running windows calc,
hWnd = FindWindow("ApplicationFrameWindow", "Calculator")
' not found? try a win7,
if hwnd = intptr.zero then
hWnd = FindWindow("CalcFrame", "Calculator")
end if
' did we find ?
if hwnd = intptr.zero then ' launch
Process.Start("calc.exe")
else
If IsIconic(hWnd) Then
ShowWindow(hWnd, ShowWindowCommands.SW_RESTORE)
Else 'bring to foreground
SetForegroundWindow(hWnd)
End If
end if
-
Aug 29th, 2015, 05:10 PM
#37
Frenzied Member
Re: AppActivate and FindWindow
 Originally Posted by Edgemeal
Calling Windows APIs are so fast I would just look for both types are not worry about windows versions and setting manifests, etc..., something like...
Code:
' find a running windows calc,
hWnd = FindWindow("ApplicationFrameWindow", "Calculator")
' not found? try a win7,
if hwnd = intptr.zero then
hWnd = FindWindow("CalcFrame", "Calculator")
end if
' did we find ?
if hwnd = intptr.zero then ' launch
Process.Start("calc.exe")
else
If IsIconic(hWnd) Then
ShowWindow(hWnd, ShowWindowCommands.SW_RESTORE)
Else 'bring to foreground
SetForegroundWindow(hWnd)
End If
end if
Nice. Makes sense. Thanks.
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
|