public static void FreeConsole() { if (!WinCon.FreeConsole()) { throw new IOException("Unable to free console", Marshal.GetLastWin32Error()); } }
private void ExitCmdProcess() { // Release attachment to the child process console. WinCon.FreeConsole(); this.UIRoot = null; if (this.job != IntPtr.Zero) { WinBase.TerminateJobObject(this.job, 0); } this.job = IntPtr.Zero; }
private void ExitProcess() { Globals.SweepAllModules(this.context); // Release attachment to the child process console. WinCon.FreeConsole(); this.UIRoot = null; if (this.job != IntPtr.Zero) { WinBase.TerminateJobObject(this.job, 0); } this.job = IntPtr.Zero; }
public void CheckClose() { string closeTestCmdLine = $"{closeTestBinaryLocation} -n {processCount} --log {testPipeName} --delay 1000 --no-realloc"; using (var tokenSource = new CancellationTokenSource()) { var token = tokenSource.Token; Task.Run(() => MakePipeServer(token), token); Log.Comment("Connect a test console window to the close test binary and wait for a few seconds."); CmdApp app = new CmdApp(CreateType.ProcessOnly, TestContext, closeTestCmdLine); Thread.Sleep(TimeSpan.FromSeconds(2)); NativeMethods.Win32BoolHelper(WinCon.FreeConsole(), "Free console bindings so we aren't shut down when we kill the window."); Log.Comment("Click the close button on the window then wait a few seconds for it to cleanup."); app.GetCloseButton().Click(); Thread.Sleep(TimeSpan.FromSeconds(5)); tokenSource.Cancel(); Log.Comment("Compare the output we received on our pipes to what we expected to get in terms of ordering and process count."); for (uint i = 1; i <= processCount; i++) { string expected = string.Format(attachPattern, i); Verify.AreEqual(expected, messages.Dequeue()); } Verify.IsTrue(messages.Dequeue().StartsWith(spacerStartsWith)); for (uint i = processCount; i >= 1; i--) { string expected; expected = string.Format(pausingPattern, i); Verify.AreEqual(expected, messages.Dequeue()); expected = string.Format(exitingPattern, i); Verify.AreEqual(expected, messages.Dequeue()); } } }
private void CreateCmdProcess(string path, string link = "") { //string AdminPrefix = "Administrator: "; string WindowTitleToFind = "Host.Tests.UIA window under test"; job = WinBase.CreateJobObject(IntPtr.Zero, IntPtr.Zero); NativeMethods.Win32NullHelper(job, "Creating job object to hold binaries under test."); Log.Comment("Attempting to launch command-line application at '{0}'", path); string binaryToRunPath = path; #if __INSIDE_WINDOWS string launchArgs = binaryToRunPath; #else string openConsolePath = Path.Combine(this.context.TestDeploymentDir, "OpenConsole.exe"); string launchArgs = $"{openConsolePath} {binaryToRunPath}"; #endif WinBase.STARTUPINFO si = new WinBase.STARTUPINFO(); si.cb = Marshal.SizeOf(si); // If we were given a LNK file to startup with, set the STARTUPINFO structure to pass that information in to the console host. if (!string.IsNullOrEmpty(link)) { si.dwFlags |= WinBase.STARTF.STARTF_TITLEISLINKNAME; si.lpTitle = link; } WinBase.PROCESS_INFORMATION pi = new WinBase.PROCESS_INFORMATION(); NativeMethods.Win32BoolHelper(WinBase.CreateProcess(null, launchArgs, IntPtr.Zero, IntPtr.Zero, false, WinBase.CP_CreationFlags.CREATE_NEW_CONSOLE | WinBase.CP_CreationFlags.CREATE_SUSPENDED, IntPtr.Zero, null, ref si, out pi), "Attempting to create child host window process."); Log.Comment($"Host window PID: {pi.dwProcessId}"); NativeMethods.Win32BoolHelper(WinBase.AssignProcessToJobObject(job, pi.hProcess), "Assigning new host window (suspended) to job object."); NativeMethods.Win32BoolHelper(-1 != WinBase.ResumeThread(pi.hThread), "Resume host window process now that it is attached and its launch of the child application will be caught in the job object."); Globals.WaitForTimeout(); WinBase.JOBOBJECT_BASIC_PROCESS_ID_LIST list = new WinBase.JOBOBJECT_BASIC_PROCESS_ID_LIST(); list.NumberOfAssignedProcesses = 2; int listptrsize = Marshal.SizeOf(list); IntPtr listptr = Marshal.AllocHGlobal(listptrsize); Marshal.StructureToPtr(list, listptr, false); TimeSpan totalWait = TimeSpan.Zero; TimeSpan waitLimit = TimeSpan.FromSeconds(30); TimeSpan pollInterval = TimeSpan.FromMilliseconds(500); while (totalWait < waitLimit) { WinBase.QueryInformationJobObject(job, WinBase.JOBOBJECTINFOCLASS.JobObjectBasicProcessIdList, listptr, listptrsize, IntPtr.Zero); list = (WinBase.JOBOBJECT_BASIC_PROCESS_ID_LIST)Marshal.PtrToStructure(listptr, typeof(WinBase.JOBOBJECT_BASIC_PROCESS_ID_LIST)); if (list.NumberOfAssignedProcesses > 1) { break; } else if (list.NumberOfAssignedProcesses < 1) { Verify.Fail("Somehow we lost the one console host process in the job already."); } Thread.Sleep(pollInterval); totalWait += pollInterval; } Verify.IsLessThan(totalWait, waitLimit); WinBase.QueryInformationJobObject(job, WinBase.JOBOBJECTINFOCLASS.JobObjectBasicProcessIdList, listptr, listptrsize, IntPtr.Zero); list = (WinBase.JOBOBJECT_BASIC_PROCESS_ID_LIST)Marshal.PtrToStructure(listptr, typeof(WinBase.JOBOBJECT_BASIC_PROCESS_ID_LIST)); Verify.AreEqual(list.NumberOfAssignedProcesses, list.NumberOfProcessIdsInList); #if __INSIDE_WINDOWS pid = pi.dwProcessId; #else // Take whichever PID isn't the host window's PID as the child. pid = pi.dwProcessId == (int)list.ProcessId ? (int)list.ProcessId2 : (int)list.ProcessId; Log.Comment($"Child command app PID: {pid}"); #endif // Free any attached consoles and attach to the console we just created. // The driver will bind our calls to the Console APIs into the child process. // This will allow us to use the APIs to get/set the console state of the test window. NativeMethods.Win32BoolHelper(WinCon.FreeConsole(), "Free existing console bindings."); // need to wait a bit or we might not be able to reliably attach System.Threading.Thread.Sleep(Globals.Timeout); NativeMethods.Win32BoolHelper(WinCon.AttachConsole((uint)pid), "Bind to the new PID for console APIs."); // we need to wait here for a bit or else // setting the console window title will fail. System.Threading.Thread.Sleep(Globals.Timeout * 5); NativeMethods.Win32BoolHelper(WinCon.SetConsoleTitle(WindowTitleToFind), "Set the window title so AppDriver can find it."); DesiredCapabilities appCapabilities = new DesiredCapabilities(); appCapabilities.SetCapability("app", @"Root"); Session = new IOSDriver <IOSElement>(new Uri(AppDriverUrl), appCapabilities); Verify.IsNotNull(Session); Actions = new Actions(Session); Verify.IsNotNull(Session); Globals.WaitForTimeout(); // If we are running as admin, the child window title will have a prefix appended as it will also run as admin. //if (IsRunningAsAdmin()) //{ // WindowTitleToFind = $"{AdminPrefix}{WindowTitleToFind}"; //} Log.Comment($"Searching for window title '{WindowTitleToFind}'"); this.UIRoot = Session.FindElementByName(WindowTitleToFind); this.hStdOut = WinCon.GetStdHandle(WinCon.CONSOLE_STD_HANDLE.STD_OUTPUT_HANDLE); Verify.IsNotNull(this.hStdOut, "Ensure output handle is valid."); this.hStdErr = WinCon.GetStdHandle(WinCon.CONSOLE_STD_HANDLE.STD_ERROR_HANDLE); Verify.IsNotNull(this.hStdErr, "Ensure error handle is valid."); // Set the timeout to 15 seconds after we found the initial window. Session.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(15); }