Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(83)

Side by Side Diff: experimental/visual_studio_plugin/src/NaClVsx.Package/NaClVsx.Package_IntegrationTestProject/IntegrationTest Library/DialogboxPurger.cs

Issue 10928195: First round of dead file removal (Closed) Base URL: https://github.com/samclegg/nativeclient-sdk.git@master
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1
2 namespace Microsoft.VsSDK.IntegrationTestLibrary
3 {
4 using System;
5 using System.Collections.Generic;
6 using System.Text;
7 using System.Runtime.InteropServices;
8 using System.Threading;
9 using Microsoft.VisualStudio.Shell.Interop;
10 using Microsoft.VisualStudio.Shell;
11
12 /// <summary>
13 /// This class is responsible to close dialog boxes that pop up during diffe rent VS Calls
14 /// </summary>
15 internal class DialogBoxPurger : IDisposable
16 {
17 /// <summary>
18 /// The default number of milliseconds to wait for the threads to signal to terminate.
19 /// </summary>
20 private const int DefaultMillisecondsToWait = 3500;
21
22 /// <summary>
23 /// Object used for synchronization between thread calls.
24 /// </summary>
25 internal static volatile object Mutex = new object();
26
27 /// <summary>
28 /// The IVsUIShell. This cannot be queried on the working thread from th e service provider. Must be done in the main thread.!!
29 /// </summary>
30 private IVsUIShell uiShell;
31
32 /// <summary>
33 /// The button to "press" on the dialog.
34 /// </summary>
35 private int buttonAction;
36
37 /// <summary>
38 /// Thread signales to the calling thread that it is done.
39 /// </summary>
40 private bool exitThread = false;
41
42 /// <summary>
43 /// Calling thread signales to this thread to die.
44 /// </summary>
45 private AutoResetEvent threadDone = new AutoResetEvent(false);
46
47 /// <summary>
48 /// The queued thread started.
49 /// </summary>
50 private AutoResetEvent threadStarted = new AutoResetEvent(false);
51
52 /// <summary>
53 /// The result of the dialogbox closing for all the dialog boxes. That i s if there are two of them and one fails this will be false.
54 /// </summary>
55 private bool dialogBoxCloseResult = false;
56
57 /// <summary>
58 /// The expected text to see on the dialog box. If set the thread will c ontinue finding the dialog box with this text.
59 /// </summary>
60 private string expectedDialogBoxText = String.Empty;
61
62 /// <summary>
63 /// The number of the same dialog boxes to wait for.
64 /// This is for scenarios when two dialog boxes with the same text are p opping up.
65 /// </summary>
66 private int numberOfDialogsToWaitFor = 1;
67
68 /// <summary>
69 /// Has the object been disposed.
70 /// </summary>
71 private bool isDisposed;
72
73 /// <summary>
74 /// Overloaded ctor.
75 /// </summary>
76 /// <param name="buttonAction">The botton to "press" on the dialog box.< /param>
77 /// <param name="numberOfDialogsToWaitFor">The number of dialog boxes wi th the same message to wait for. This is the situation when the same action pops up two of the same dialog boxes</param>
78 /// <param name="expectedDialogMesssage">The expected dialog box message to check for.</param>
79 internal DialogBoxPurger(int buttonAction, int numberOfDialogsToWaitFor, string expectedDialogMesssage)
80 {
81 this.buttonAction = buttonAction;
82 this.numberOfDialogsToWaitFor = numberOfDialogsToWaitFor;
83 this.expectedDialogBoxText = expectedDialogMesssage;
84 }
85
86 /// <summary>
87 /// Overloaded ctor.
88 /// </summary>
89 /// <param name="buttonAction">The botton to "press" on the dialog box.< /param>
90 /// <param name="numberOfDialogsToWaitFor">The number of dialog boxes wi th the same message to wait for. This is the situation when the same action pops up two of the same dialog boxes</param>
91 internal DialogBoxPurger(int buttonAction, int numberOfDialogsToWaitFor)
92 {
93 this.buttonAction = buttonAction;
94 this.numberOfDialogsToWaitFor = numberOfDialogsToWaitFor;
95 }
96
97 /// <summary>
98 /// Overloaded ctor.
99 /// </summary>
100 /// <param name="buttonAction">The botton to "press" on the dialog box.< /param>
101 /// <param name="expectedDialogMesssage">The expected dialog box message to check for.</param>
102 internal DialogBoxPurger(int buttonAction, string expectedDialogMesssage )
103 {
104 this.buttonAction = buttonAction;
105 this.expectedDialogBoxText = expectedDialogMesssage;
106 }
107
108 /// <summary>
109 /// Overloaded ctor.
110 /// </summary>
111 /// <param name="buttonAction">The botton to "press" on the dialog box.< /param>
112 internal DialogBoxPurger(int buttonAction)
113 {
114 this.buttonAction = buttonAction;
115 }
116
117 /// <summary>
118 #region IDisposable Members
119
120 void IDisposable.Dispose()
121 {
122 if (this.isDisposed)
123 {
124 return;
125 }
126
127 this.WaitForDialogThreadToTerminate();
128
129 this.isDisposed = true;
130 }
131
132 /// <summary>
133 /// Spawns a thread that will start listening to dialog boxes.
134 /// </summary>
135 internal void Start()
136 {
137 // We ask for the uishell here since we cannot do that on the therad that we will spawn.
138 IVsUIShell uiShell = Package.GetGlobalService(typeof(SVsUIShell)) as IVsUIShell;
139
140 if (uiShell == null)
141 {
142 throw new InvalidOperationException("Could not get the uiShell f rom the serviceProvider");
143 }
144
145 this.uiShell = uiShell;
146
147 System.Threading.Thread thread = new System.Threading.Thread(new Thr eadStart(this.HandleDialogBoxes));
148 thread.Start();
149
150 // We should never deadlock here, hence do not use the lock. Wait to be sure that the thread started.
151 this.threadStarted.WaitOne(3500, false);
152 }
153
154 /// <summary>
155 /// Waits for the dialog box close thread to terminate. If the thread do es not signal back within millisecondsToWait that it is shutting down,
156 /// then it will tell to the thread to do it.
157 /// </summary>
158 internal bool WaitForDialogThreadToTerminate()
159 {
160 return this.WaitForDialogThreadToTerminate(DefaultMillisecondsToWait );
161 }
162
163 /// <summary>
164 /// Waits for the dialog box close thread to terminate. If the thread do es not signal back within millisecondsToWait that it is shutting down,
165 /// then it will tell to the thread to do it.
166 /// </summary>
167 /// <param name="millisecondsToWait">The number milliseconds to wait for until the dialog purger thread is signaled to terminate. This is just for safe precaution that we do not hang. </param>
168 /// <returns>The result of the dialog boxes closing</returns>
169 internal bool WaitForDialogThreadToTerminate(int numberOfMillisecondsToW ait)
170 {
171 bool signaled = false;
172
173 // We give millisecondsToWait sec to bring up and close the dialog b ox.
174 signaled = this.threadDone.WaitOne(numberOfMillisecondsToWait, false );
175
176 // Kill the thread since a timeout occured.
177 if (!signaled)
178 {
179 lock (Mutex)
180 {
181 // Set the exit thread to true. Next time the thread will ki ll itselfes if it sees
182 this.exitThread = true;
183 }
184
185 // Wait for the thread to finish. We should never deadlock here.
186 this.threadDone.WaitOne();
187 }
188
189 return this.dialogBoxCloseResult;
190 }
191
192 /// <summary>
193 /// This is the thread method.
194 /// </summary>
195 private void HandleDialogBoxes()
196 {
197 // No synchronization numberOfDialogsToWaitFor since it is readonly
198 IntPtr[] hwnds = new IntPtr[this.numberOfDialogsToWaitFor];
199 bool[] dialogBoxCloseResults = new bool[this.numberOfDialogsToWaitFo r];
200
201 try
202 {
203 // Signal that we started
204 lock (Mutex)
205 {
206 this.threadStarted.Set();
207 }
208
209 // The loop will be exited either if a message is send by the ca ller thread or if we found the dialog. If a message box text is specified the lo op will not exit until the dialog is found.
210 bool stayInLoop = true;
211 int dialogBoxesToWaitFor = 1;
212
213 while (stayInLoop)
214 {
215 int hwndIndex = dialogBoxesToWaitFor - 1;
216
217 // We need to lock since the caller might set context to nul l.
218 lock (Mutex)
219 {
220 if (this.exitThread)
221 {
222 break;
223 }
224
225 // We protect the shell too from reentrency.
226 this.uiShell.GetDialogOwnerHwnd(out hwnds[hwndIndex]);
227
228 }
229
230 if (hwnds[hwndIndex] != IntPtr.Zero)
231 {
232 StringBuilder windowClassName = new StringBuilder(256);
233 NativeMethods.GetClassName(hwnds[hwndIndex], windowClass Name, windowClassName.Capacity);
234
235 // The #32770 is the class name of a messagebox dialog.
236 if (windowClassName.ToString().Contains("#32770"))
237 {
238 IntPtr unmanagedMemoryLocation = IntPtr.Zero;
239 string dialogBoxText = String.Empty;
240 try
241 {
242 unmanagedMemoryLocation = Marshal.AllocHGlobal(1 0 * 1024);
243 NativeMethods.EnumChildWindows(hwnds[hwndIndex], new NativeMethods.CallBack(FindMessageBoxString), unmanagedMemoryLocation);
244 dialogBoxText = Marshal.PtrToStringUni(unmanaged MemoryLocation);
245 }
246 finally
247 {
248 if (unmanagedMemoryLocation != IntPtr.Zero)
249 {
250 Marshal.FreeHGlobal(unmanagedMemoryLocation) ;
251 }
252 }
253
254 lock (Mutex)
255 {
256
257 // Since this is running on the main thread be s ure that we close the dialog.
258 bool dialogCloseResult = false;
259 if (this.buttonAction != 0)
260 {
261 dialogCloseResult = NativeMethods.EndDialog( hwnds[hwndIndex], this.buttonAction);
262 }
263
264 // Check if we have found the right dialog box.
265 if (String.IsNullOrEmpty(this.expectedDialogBoxT ext) || (!String.IsNullOrEmpty(dialogBoxText) && String.Compare(this.expectedDia logBoxText, dialogBoxText.Trim(), StringComparison.OrdinalIgnoreCase) == 0))
266 {
267 dialogBoxCloseResults[hwndIndex] = dialogClo seResult;
268 if (dialogBoxesToWaitFor++ >= this.numberOfD ialogsToWaitFor)
269 {
270 stayInLoop = false;
271 }
272 }
273 }
274 }
275 }
276 }
277 }
278 finally
279 {
280 //Let the main thread run a possible close command.
281 System.Threading.Thread.Sleep(2000);
282
283 foreach (IntPtr hwnd in hwnds)
284 {
285 // At this point the dialog should be closed, if not attempt to close it.
286 if (hwnd != IntPtr.Zero)
287 {
288 NativeMethods.SendMessage(hwnd, NativeMethods.WM_CLOSE, 0, new IntPtr(0));
289 }
290 }
291
292 lock (Mutex)
293 {
294 // Be optimistic.
295 this.dialogBoxCloseResult = true;
296
297 for (int i = 0; i < dialogBoxCloseResults.Length; i++)
298 {
299 if (!dialogBoxCloseResults[i])
300 {
301 this.dialogBoxCloseResult = false;
302 break;
303 }
304 }
305
306 this.threadDone.Set();
307 }
308 }
309 }
310
311 /// <summary>
312 /// Finds a messagebox string on a messagebox.
313 /// </summary>
314 /// <param name="hwnd">The windows handle of the dialog</param>
315 /// <param name="unmanagedMemoryLocation">A pointer to the memorylocatio n the string will be written to</param>
316 /// <returns>True if found.</returns>
317 private static bool FindMessageBoxString(IntPtr hwnd, IntPtr unmanagedMe moryLocation)
318 {
319 StringBuilder sb = new StringBuilder(512);
320 NativeMethods.GetClassName(hwnd, sb, sb.Capacity);
321
322 if (sb.ToString().ToLower().Contains("static"))
323 {
324 StringBuilder windowText = new StringBuilder(2048);
325 NativeMethods.GetWindowText(hwnd, windowText, windowText.Capacit y);
326
327 if (windowText.Length > 0)
328 {
329 IntPtr stringAsPtr = IntPtr.Zero;
330 try
331 {
332 stringAsPtr = Marshal.StringToHGlobalAnsi(windowText.ToS tring());
333 char[] stringAsArray = windowText.ToString().ToCharArray ();
334
335 // Since unicode characters are copied check if we are o ut of the allocated length.
336 // If not add the end terminating zero.
337 if ((2 * stringAsArray.Length) + 1 < 2048)
338 {
339 Marshal.Copy(stringAsArray, 0, unmanagedMemoryLocati on, stringAsArray.Length);
340 Marshal.WriteInt32(unmanagedMemoryLocation, 2 * stri ngAsArray.Length, 0);
341 }
342 }
343 finally
344 {
345 if (stringAsPtr != IntPtr.Zero)
346 {
347 Marshal.FreeHGlobal(stringAsPtr);
348 }
349 }
350 return false;
351 }
352 }
353
354 return true;
355 }
356
357 #endregion
358 }
359 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698