问题
We have implemented a solution to give our internal users a nag message that they need to redeploy our application. We are using the filesystem watcher to monitor the network and look for a change in a specific file which has worked very well. Most of the functionality has been implemented in a base form class that most of the forms of our application inherit from. A new message box will be displayed every five minutes until the redeploy the app. It nags them enough that its effective in getting them to redeploy but lets them finish up whatever their doing if they need to.
The problem were running into if the user is away from their desk they might have 20+ message boxes when they return. So what we're trying to do is figure out if they have dismissed the message box or not. If they haven't dismissed no reason to display another one.
They not only can have multiple our different applications running that implement this functionality they also can have multiple of the very same app running just connected to a different environment.
I was successful in finding the message boxes with FindWindow but i didn't know which specific instance of which application it belongs to so i can't just assume it belongs to the current instance. I was hoping FindWindowEx work by just passing the handle of the owner of the message box into the api call but i haven't been successful. It always returns zero.
The code i will be showing is in vb.net but i'm proficient in both c# & vb.net so it doesn't matter what form the solution comes in.
Anyways here is out code that throws up the notification:
Private Sub InitDeploymentCheck()
moDeploymentCheck = New TRS.Deployment.TRSDeploymentCheck(EnvironmentVariables.Environment, AppDomain.CurrentDomain.BaseDirectory.Contains("bin"), MDIMain)
AddHandler moDeploymentCheck.DeploymentNeeded,
Sub()
moTimer = New Timer()
moTimer.Interval = 300000 '5 minutes
moTimer.Enabled = True
AddHandler moTimer.Tick,
Sub()
'check to see if the message box exist or not before throwing up a new one
MessageBox.Show(MDIMain, "There is a recent critical deployment, please re-deploy STAR to get latest changes.", "Critical Deployment", MessageBoxButtons.OK, MessageBoxIcon.Warning)
End Sub
MessageBox.Show(MDIMain, "There is a recent critical deployment, please re-deploy STAR to get latest changes.", "Critical Deployment", MessageBoxButtons.OK, MessageBoxIcon.Warning)
End Sub
I was able to find the window:
Dim handle As IntPtr = FindWindow(Nothing, "Critical Deployment")
This i how i tried to find the window with FindWindowEX:
Dim t As IntPtr = FindWindowEx(200398, IntPtr.Zero, "Form", "Critical Deployment")
200398 is the handle from mdimain above.
回答1:
Once you have the HWND
handle to a window, you can use GetWindowLong(GWL_HINSTANCE)
or GetWindowThreadProcessId()
to check which application instance the window belongs to. Use EnumWindows()
to enumerate all top-level windows, where your callback function checks the title and process instance of each reported window until you find a match you are looking for.
回答2:
Why not just use a named EventWaitHandle that indicates whether one of those message boxes is currently displayed? All of your applications could subscribe to that event. When an application sees that it's time to display the message box, it checks to see if the wait handle is set. If it's not set, then the application sets the event and displays the message box. When the message box is dismissed, the application resets the event. If the event is set when checked, the application just doesn't display the message.
That's a whole lot easier than FindWindow
and EnumWindows
.
来源:https://stackoverflow.com/questions/13592290/finding-a-messagebox-in-a-specific-app