/// <summary> /// Event Handler - listens to events in the hook manager. /// Sends the new messege to the backgound worker of the mainlogic. /// the background worker will prosess all the data and will send updates to the GUI when it is done. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public void Manager_WindowChanged(object sender, WindowChangedEventArgs e) { if (!backgroundLogic.managerWindowChangedWorker.IsBusy) { backgroundLogic.managerWindowChangedWorker.RunWorkerAsync(); } }
protected void OnFocusChange(WindowChangedEventArgs eventArgs) { if (FocusChange != null) { FocusChange.Invoke(this, eventArgs); } }
private void OnVbeFocusChanged(object sender, WindowChangedEventArgs e) { if (e.EventType == FocusType.GotFocus) { switch (e.Window.Type) { case WindowKind.Designer: //Designer or control on designer form selected. if (e.Window == null || e.Window.IsWrappingNullReference || e.Window.Type != WindowKind.Designer) { return; } new Task(() => DispatchSelectedDesignerDeclaration(_vbe.SelectedVBComponent)).Start(); break; case WindowKind.CodeWindow: //Caret changed in a code pane. if (e.CodePane != null && !e.CodePane.IsWrappingNullReference) { new Task(() => DispatchSelectedDeclaration(new DeclarationChangedEventArgs(e.CodePane, _parser.State.FindSelectedDeclaration(e.CodePane)))).Start(); } break; } } else if (e.EventType == FocusType.ChildFocus) { //Treeview selection changed in project window. new Task(() => DispatchSelectedProjectNodeDeclaration(_vbe.SelectedVBComponent)).Start(); } }
/// <summary> /// Called if the active window changes. /// </summary> /// <param name="e"></param> protected void OnActiveWindowChangedEvent(WindowChangedEventArgs e) { if (this.ActiveWindowChangedEvent != null) { this.ActiveWindowChangedEvent(this, e); } }
private void OnVbeFocusChanged(object sender, WindowChangedEventArgs e) { if (e.EventType == FocusType.GotFocus) { switch (e.Hwnd.ToWindowType()) { case WindowType.DesignerWindow: Task.Run(() => { using (var component = _vbe.SelectedVBComponent) { DispatchSelectedDesignerDeclaration(component); } }); break; case WindowType.CodePane: //Caret changed in a code pane. Task.Run(() => { using (var pane = VbeNativeServices.GetCodePaneFromHwnd(e.Hwnd)) { var selection = pane.GetQualifiedSelection(); if (!selection.HasValue) { return; } var selectedDeclaration = _selectedDeclarationProvider.SelectedDeclaration(selection.Value); var eventArgs = new DeclarationChangedEventArgs(_vbe, selectedDeclaration); DispatchSelectedDeclaration(eventArgs); } }); break; } } else if (e.EventType == FocusType.ChildFocus) { //Treeview selection changed in project window. Task.Run(() => { using (var component = _vbe.SelectedVBComponent) { DispatchSelectedProjectNodeDeclaration(component); } }); } }
private void OnVbeFocusChanged(object sender, WindowChangedEventArgs e) { if (e.EventType == FocusType.GotFocus) { switch (e.Hwnd.ToWindowType()) { case WindowType.DesignerWindow: Task.Run(() => { using (var component = _vbe.SelectedVBComponent) { DispatchSelectedDesignerDeclaration(component); } }); break; case WindowType.CodePane: //Caret changed in a code pane. Task.Run(() => { using (var pane = VbeNativeServices.GetCodePaneFromHwnd(e.Hwnd)) { DispatchSelectedDeclaration( new DeclarationChangedEventArgs(_vbe, _parser.State.FindSelectedDeclaration(pane))); } }); break; } } else if (e.EventType == FocusType.ChildFocus) { //Treeview selection changed in project window. Task.Run(() => { using (var component = _vbe.SelectedVBComponent) { DispatchSelectedProjectNodeDeclaration(component); } }); } }
/// <summary> /// Reports that an element value has changed. /// </summary> /// <param name="elementid">DWORD value representing a particular entry in the array of element values associated with the selection context. For valid elementid values, see VSConstants.VSSELELEMID.</param> /// <param name="varValueOld">VARIANT that contains the previous element value. This parameter contains element-specific data, such as a pointer to the IOleCommandTarget interface if elementid is set to SEID_ResultsList or a pointer to the IOleUndoManager interface if elementid is set to SEID_UndoManager.</param> /// <param name="varValueNew">VARIANT that contains the new element value. This parameter contains element-specific data, such as a pointer to the IOleCommandTarget interface if elementid is set to SEID_ResultsList or a pointer to the IOleUndoManager interface if elementid is set to SEID_UndoManager.</param> /// <returns>If the method succeeds, it returns S_OK. If it fails, it returns an error code.</returns> public virtual int OnElementValueChanged(uint elementid, object varValueOld, object varValueNew) { if (elementid == (uint)VSConstants.VSSELELEMID.SEID_WindowFrame) { IVsWindowFrame oldFrame = (IVsWindowFrame)varValueOld; IVsWindowFrame newFrame = (IVsWindowFrame)varValueNew; WindowChangedEventArgs args = new WindowChangedEventArgs(); if (oldFrame != null) { args.OldData = ParseFrame(oldFrame); } if (newFrame != null) { args.NewData = ParseFrame(newFrame); } this.OnActiveWindowChangedEvent(args); } return(VSConstants.S_OK); }
private void WatchWindow() { IntPtr handle; try { handle = process.MainWindowHandle; } catch (Exception e) { Util.Logging.Log(e); return; } Windows.FindWindow.TextComparer classCallback = new Windows.FindWindow.TextComparer( delegate(string name, StringBuilder sb) { if (sb.Length == EDIT_CLASSNAME.Length) { return(sb.ToString().Equals(EDIT_CLASSNAME)); } return(false); }); Windows.FindWindow.TextComparer textCallback = new Windows.FindWindow.TextComparer( delegate(string name, StringBuilder sb) { if (name != null && name.Equals(EDIT_CLASSNAME)) { return(sb.Length > 500 && sb[0] == '*'); } return(true); }); StringBuilder buffer = new StringBuilder(DX_WINDOW_CLASSNAME.Length); int length = 0; var wce = new WindowChangedEventArgs(); var _handle = IntPtr.Zero; //watched for windowed mode process exit with no handle -- likely an invisible crash due to outdated Local.dat do { try { process.Refresh(); handle = process.MainWindowHandle; } catch (Exception e) { Util.Logging.Log(e); } try { if (this.process.HasExited) { if (handle == IntPtr.Zero && (IsAutomaticLogin(this.Account.Settings) || Util.Args.Contains(this.Args, "nopatchui"))) { var elapsed = this.process.ExitTime.Subtract(this.process.StartTime).TotalSeconds; if (elapsed < 60 && WindowCrashed != null) { WindowCrashed(this, CrashReason.NoPatchUI); } } break; } } catch (Exception e) { Util.Logging.Log(e); return; } if (handle != IntPtr.Zero) { if (_handle != handle) { _handle = handle; wce.Handle = handle; if (WindowChanged != null) { wce.Type = WindowChangedEventArgs.EventType.HandleChanged; WindowChanged(this, wce); } } buffer.Length = 0; NativeMethods.GetClassName(handle, buffer, buffer.Capacity + 1); int l; if ((l = buffer.Length) != length) { length = l; if (l > 0) { string className = buffer.ToString(); if (className.Equals(DX_WINDOW_CLASSNAME)) { if (WindowChanged != null) { wce.Type = WindowChangedEventArgs.EventType.DxWindowCreated; WindowChanged(this, wce); } try { var t = DateTime.UtcNow.AddSeconds(30); do { buffer.Length = 0; if (NativeMethods.GetWindowText(handle, buffer, 2) > 0 && buffer[0] != 'U') //window text is initially Untitled { if (WindowChanged != null) { wce.Type = WindowChangedEventArgs.EventType.TitleChanged; WindowChanged(this, wce); } break; } }while (DateTime.UtcNow < t && !process.WaitForExit(100)); } catch (Exception e) { Util.Logging.Log(e); } using (var volumeControl = new Windows.Volume.VolumeControl(process.Id)) { //already loaded if audio is initialized (only checks default playback device) var hasVolume = volumeControl.Query(); if (hasVolume) { if (WindowChanged != null && !this.process.HasExited) { wce.Type = WindowChangedEventArgs.EventType.DxWindowReady; WindowChanged(this, wce); } return; } var nextCheck_Seconds = 3; var memoryUsage = process.PeakWorkingSet64; var limit = DateTime.UtcNow.AddMinutes(3); var nextCheck = DateTime.UtcNow.AddSeconds(nextCheck_Seconds); var memoryChecks = 0; //var verified = false; do { //the volume will be initialized first, then a child process (CoherentUI) will spawn if (hasVolume = volumeControl.Query() || HasChildProcess(process.Id)) { break; } //watching for changes in memory usage to check if it's still doing something //bypassing the launching can cause it to get stuck on authentication if either the credentials are wrong or the network isn't authorized if (watchAutologin && DateTime.UtcNow > nextCheck) { process.Refresh(); var memoryChange = process.PeakWorkingSet64 - memoryUsage; memoryUsage += memoryChange; if (memoryChange < 1000000) { if (++memoryChecks == 3) { //this account may be stuck trying to authenticate var account = this.Account.Settings; if (account.HasCredentials && account.NetworkAuthorizationState != Settings.NetworkAuthorizationState.Disabled && Settings.NetworkAuthorization.HasValue) { if (account.NetworkAuthorizationState == Settings.NetworkAuthorizationState.Unknown) { if (AuthenticationRequired != null) { AuthenticationRequired(this, null); } return; } else { Tools.ArenaAccount session; switch (NetworkAuthorization.Verify(account, true, null, out session)) { case NetworkAuthorization.VerifyResult.Completed: case NetworkAuthorization.VerifyResult.Required: if (AuthenticationRequired != null) { AuthenticationRequired(this, session); } return; case NetworkAuthorization.VerifyResult.OK: //authentication was ok - assuming it's a slow load nextCheck_Seconds = 10; //verified = true; break; case NetworkAuthorization.VerifyResult.None: default: //authentication isn't being tracked - assuming it's stuck nextCheck_Seconds = 10; break; } } } else { //authentication isn't enabled nextCheck_Seconds = 10; } } else if (memoryChecks > 6) { if (AuthenticationRequired != null) { AuthenticationRequired(this, null); } return; } } else { memoryChecks = 0; } nextCheck = DateTime.UtcNow.AddSeconds(nextCheck_Seconds); } }while (DateTime.UtcNow < limit && !this.process.WaitForExit(500)); if (WindowChanged != null && !this.process.HasExited) { wce.Type = WindowChangedEventArgs.EventType.DxWindowReady; WindowChanged(this, wce); } return; } } else if (className[0] == '#') { var result = Find(handle, classCallback, textCallback); if (result != null) { CrashReason reason = CrashReason.Unknown; string text = result.Text; int i = text.IndexOf("Assertion:", 0, 100); if (i != -1) { int j = text.IndexOf('\n', i); if (text.IndexOf("Is your archive up to date?", i, j - i, StringComparison.OrdinalIgnoreCase) != -1 || text.IndexOf("Client needs to be patched", i, j - i, StringComparison.OrdinalIgnoreCase) != -1) { reason = CrashReason.PatchRequired; } } if (WindowCrashed != null) { WindowCrashed(this, reason); } } return; } else if (className.Equals(LAUNCHER_WINDOW_CLASSNAME)) { if (WindowChanged != null) { wce.Type = WindowChangedEventArgs.EventType.TitleChanged; WindowChanged(this, wce); } } } } } }while (!process.WaitForExit(500) && this.watcher != null); }
protected virtual void OnWindowChanged() { WindowChangedEventArgs args = new WindowChangedEventArgs(); WindowChanged?.Invoke(this, args); }
/// <summary> /// Called if the active window changes. /// </summary> /// <param name="e"></param> protected void OnActiveWindowChangedEvent(WindowChangedEventArgs e) { if (this.ActiveWindowChangedEvent != null) this.ActiveWindowChangedEvent(this, e); }
/// <summary> /// Reports that an element value has changed. /// </summary> /// <param name="elementid">DWORD value representing a particular entry in the array of element values associated with the selection context. For valid elementid values, see VSConstants.VSSELELEMID.</param> /// <param name="varValueOld">VARIANT that contains the previous element value. This parameter contains element-specific data, such as a pointer to the IOleCommandTarget interface if elementid is set to SEID_ResultsList or a pointer to the IOleUndoManager interface if elementid is set to SEID_UndoManager.</param> /// <param name="varValueNew">VARIANT that contains the new element value. This parameter contains element-specific data, such as a pointer to the IOleCommandTarget interface if elementid is set to SEID_ResultsList or a pointer to the IOleUndoManager interface if elementid is set to SEID_UndoManager.</param> /// <returns>If the method succeeds, it returns S_OK. If it fails, it returns an error code.</returns> public virtual int OnElementValueChanged(uint elementid, object varValueOld, object varValueNew) { if (elementid == (uint)VSConstants.VSSELELEMID.SEID_WindowFrame) { IVsWindowFrame oldFrame = (IVsWindowFrame)varValueOld; IVsWindowFrame newFrame = (IVsWindowFrame)varValueNew; WindowChangedEventArgs args = new WindowChangedEventArgs(); if (oldFrame != null) { args.OldData = ParseFrame(oldFrame); } if (newFrame != null) { args.NewData = ParseFrame(newFrame); } this.OnActiveWindowChangedEvent(args); } return VSConstants.S_OK; }
/// <summary> /// the general subscriber for all windows events. /// each objects publishes an event with the same delegate. they all sbscribed here. /// if the window title or the process have changed - than invoke the rest of the events in the middle man and so on. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Manager_WindowChanged(object sender, WindowChangedEventArgs e) { WindowChanged?.Invoke(sender, e); }
// This runs on the Automation thread, via SyncContextAuto passed in to WinEventHook when we created this WindowWatcher // CONSIDER: We would be able to run all the watcher updates from WinEvents, including Location and Selection changes, // but since WinEvents have no hwnd filter, UIAutomation events might be more efficient. // CONSIDER: Performance optimisation would keep a list of window handles we know about, preventing the class name check every time void _windowStateChangeHook_WinEventReceived(object sender, WinEventHook.WinEventArgs e) { if (!WindowChangedEventArgs.IsSupportedWinEvent(e.EventType)) { return; } var className = Win32Helper.GetClassName(e.WindowHandle); if (e.EventType == WinEventHook.WinEvent.EVENT_OBJECT_FOCUS) { // Might raise change event for Unfocus if (!UpdateFocus(e.WindowHandle, className)) { // We already have the right focus return; } } // Debug.Print("### Thread receiving WindowStateChange: " + Thread.CurrentThread.ManagedThreadId); switch (className) { //case _sheetWindowClass: // if (e.EventType == WinEventHook.WinEvent.EVENT_OBJECT_SHOW) // { // // Maybe a new workbook is on top... // // Note that there is also an EVENT_OBJECT_PARENTCHANGE (which we are not subscribing to at the moment // } // break; case _popupListClass: PopupListWindowChanged?.Invoke(this, new WindowChangedEventArgs(e.WindowHandle, e.EventType)); break; case _inCellEditClass: InCellEditWindowChanged?.Invoke(this, new WindowChangedEventArgs(e.WindowHandle, e.EventType)); break; case _formulaBarClass: FormulaBarWindowChanged?.Invoke(this, new WindowChangedEventArgs(e.WindowHandle, e.EventType)); break; case _excelToolTipClass: ExcelToolTipWindowChanged?.Invoke(this, new WindowChangedEventArgs(e.WindowHandle, e.EventType)); break; //case _nuiDialogClass: // // Debug.Print($"SelectDataSource {_selectDataSourceClass} Window update: {e.WindowHandle:X}, EventType: {e.EventType}, idChild: {e.ChildId}"); // if (e.EventType == WinEventHook.WinEvent.EVENT_OBJECT_CREATE) // { // // Get the name of this window - maybe ours or some other NUIDialog // var windowTitle = Win32Helper.GetText(e.WindowHandle); // if (windowTitle.Equals(_selectDataSourceTitle, StringComparison.OrdinalIgnoreCase)) // { // SelectDataSourceWindow = e.WindowHandle; // SelectDataSourceWindowChanged?.Invoke(this, // new WindowChangedEventArgs { Type = WindowChangedEventArgs.ChangeType.Create }); // } // } // else if (SelectDataSourceWindow == e.WindowHandle && e.EventType == WinEventHook.WinEvent.EVENT_OBJECT_SHOW) // { // IsSelectDataSourceWindowVisible = true; // SelectDataSourceWindowChanged?.Invoke(this, // new WindowChangedEventArgs { Type = WindowChangedEventArgs.ChangeType.Create }); // } // else if (SelectDataSourceWindow == e.WindowHandle && e.EventType == WinEventHook.WinEvent.EVENT_OBJECT_HIDE) // { // IsSelectDataSourceWindowVisible = false; // SelectDataSourceWindowChanged?.Invoke(this, new WindowChangedEventArgs { Type = WindowChangedEventArgs.ChangeType.Hide }); // } // else if (SelectDataSourceWindow == e.WindowHandle && e.EventType == WinEventHook.WinEvent.EVENT_OBJECT_DESTROY) // { // IsSelectDataSourceWindowVisible = false; // SelectDataSourceWindow = IntPtr.Zero; // SelectDataSourceWindowChanged?.Invoke(this, new WindowChangedEventArgs { Type = WindowChangedEventArgs.ChangeType.Destroy }); // } // break; default: //InCellEditWindowChanged(this, EventArgs.Empty); break; } }
private void WatchWindow() { IntPtr handle; try { handle = process.MainWindowHandle; } catch (Exception e) { Util.Logging.Log(e); return; } Windows.FindWindow.TextComparer classCallback = new Windows.FindWindow.TextComparer( delegate(string name, StringBuilder sb) { if (sb.Length == EDIT_CLASSNAME.Length) { return(sb.ToString().Equals(EDIT_CLASSNAME)); } return(false); }); Windows.FindWindow.TextComparer textCallback = new Windows.FindWindow.TextComparer( delegate(string name, StringBuilder sb) { if (name != null && name.Equals(EDIT_CLASSNAME)) { return(sb.Length > 500 && sb[0] == '*'); } return(true); }); StringBuilder buffer = new StringBuilder(DX_WINDOW_CLASSNAME.Length); int length = 0; var wce = new WindowChangedEventArgs(); var _handle = IntPtr.Zero; do { try { do { process.Refresh(); handle = process.MainWindowHandle; if (handle == IntPtr.Zero) { if (!process.WaitForExit(10)) { process.WaitForInputIdle(); } } else { break; } }while (!process.HasExited); } catch (Exception e) { Util.Logging.Log(e); } try { if (this.process.HasExited) { //no longer applicable - nopatchui exiting without creating a window likely meant the client wasn't up to date //if (handle == IntPtr.Zero && (IsAutomaticLogin(this.Account.Settings) || Util.Args.Contains(this.Args, "nopatchui"))) //{ // var elapsed = this.process.ExitTime.Subtract(this.process.StartTime).TotalSeconds; // if (elapsed < 60 && WindowCrashed != null) // WindowCrashed(this, CrashReason.NoPatchUI); //} break; } } catch (Exception e) { Util.Logging.Log(e); return; } if (handle != IntPtr.Zero) { if (_handle != handle) { _handle = handle; wce.Handle = handle; if (WindowChanged != null) { wce.Type = WindowChangedEventArgs.EventType.HandleChanged; WindowChanged(this, wce); } } buffer.Length = 0; NativeMethods.GetClassName(handle, buffer, buffer.Capacity + 1); int l; if ((l = buffer.Length) != length) { length = l; if (l > 0) { string className = buffer.ToString(); if (className.Equals(DX_WINDOW_CLASSNAME)) { if (WindowChanged != null) { wce.Type = WindowChangedEventArgs.EventType.DxWindowCreated; WindowChanged(this, wce); } //window initialization order: //title change > volume (window is ready) > coherentui int pidChild = 0; bool hasVolume = false; DateTime limit; using (var volumeControl = new Windows.Volume.VolumeControl(process.Id)) { if (processWasAlreadyStarted && ((hasVolume = volumeControl.Query()) || (pidChild = GetChildProcess(process.Id)) > 0)) { //window is already loaded if (WindowChanged != null) { wce.Type = WindowChangedEventArgs.EventType.TitleChanged; WindowChanged(this, wce); } limit = DateTime.UtcNow.AddMinutes(1); } else { try { limit = DateTime.UtcNow.AddSeconds(30); var ws1 = IntPtr.Zero; do { //window style changes when loading into fullscreen mode var ws2 = NativeMethods.GetWindowLongPtr(handle, (int)GWL.GWL_STYLE); if (ws2 != ws1) { if (ws1 != IntPtr.Zero && WindowChanged != null) { wce.Type = WindowChangedEventArgs.EventType.DxWindowStyleChanged; WindowChanged(this, wce); } ws1 = ws2; } buffer.Length = 0; if (NativeMethods.GetWindowText(handle, buffer, 2) > 0 && buffer[0] != 'U') //window text is initially Untitled { if (WindowChanged != null) { wce.Type = WindowChangedEventArgs.EventType.TitleChanged; WindowChanged(this, wce); } break; } }while (DateTime.UtcNow < limit && !process.WaitForExit(100)); } catch (Exception e) { Util.Logging.Log(e); } var nextCheck_Seconds = 3; var memoryUsage = process.PeakWorkingSet64; var nextCheck = DateTime.UtcNow.AddSeconds(nextCheck_Seconds); var memoryChecks = 0; //var verified = false; limit = DateTime.UtcNow.AddMinutes(3); do { if ((hasVolume = volumeControl.Query()) || (pidChild = GetChildProcess(process.Id)) > 0) { break; } #region -nopatchui activity check (obsolete) //watching for changes in memory usage to check if it's still doing something //bypassing the launcher (-nopatchui) can cause it to get stuck on authentication if either the credentials are wrong or the network isn't authorized if (!hasVolume && DateTime.UtcNow > nextCheck) { process.Refresh(); var memoryChange = process.PeakWorkingSet64 - memoryUsage; memoryUsage += memoryChange; if (memoryChange < 1000000) { if (++memoryChecks == 3) { //this account may be stuck trying to authenticate var account = this.Account.Settings; if (account.HasCredentials && account.NetworkAuthorizationState != Settings.NetworkAuthorizationState.Disabled && Settings.NetworkAuthorization.HasValue) { if (account.NetworkAuthorizationState == Settings.NetworkAuthorizationState.Unknown) { if (AuthenticationRequired != null) { AuthenticationRequired(this, null); } return; } else { Tools.ArenaAccount session; switch (NetworkAuthorization.Verify(account, true, null, out session)) { case NetworkAuthorization.VerifyResult.Completed: case NetworkAuthorization.VerifyResult.Required: if (AuthenticationRequired != null) { AuthenticationRequired(this, session); } return; case NetworkAuthorization.VerifyResult.OK: //authentication was ok - assuming it's a slow load nextCheck_Seconds = 10; //verified = true; break; case NetworkAuthorization.VerifyResult.None: default: //authentication isn't being tracked - assuming it's stuck nextCheck_Seconds = 10; break; } } } else { //authentication isn't enabled nextCheck_Seconds = 10; } } else if (memoryChecks > 6) { if (AuthenticationRequired != null) { AuthenticationRequired(this, null); } return; } } else { memoryChecks = 0; } nextCheck = DateTime.UtcNow.AddSeconds(nextCheck_Seconds); } #endregion }while (DateTime.UtcNow < limit && !this.process.WaitForExit(500)); } } if (WindowChanged != null && !this.process.HasExited) { wce.Type = WindowChangedEventArgs.EventType.DxWindowReady; WindowChanged(this, wce); } #region Find CoherentUI if (pidChild == 0) { do { if ((pidChild = GetChildProcess(process.Id)) > 0) { break; } }while (DateTime.UtcNow < limit && !this.process.WaitForExit(500)); } if (pidChild > 0) { try { using (var child = Process.GetProcessById(pidChild)) { limit = DateTime.UtcNow.AddSeconds(10); var pid = pidChild; do { if ((pidChild = GetChildProcess(pid)) > 0) { break; } }while (DateTime.UtcNow < limit && !child.WaitForExit(500)); } if (pidChild > 0) { using (var child = Process.GetProcessById(pidChild)) { long mem = 0; byte counter = 0; limit = DateTime.UtcNow.AddSeconds(60); do { if (mem > 0) { child.Refresh(); } var _mem = child.PeakWorkingSet64; if (_mem > mem) { mem = _mem; counter = 0; } else if (++counter > 2) { break; } }while (DateTime.UtcNow < limit && !child.WaitForExit(100)); } } } catch (Exception ex) { Util.Logging.Log(ex); } } #endregion if (WindowChanged != null && !this.process.HasExited) { wce.Type = WindowChangedEventArgs.EventType.InGameCoherentUIReady; WindowChanged(this, wce); } return; } else if (className[0] == '#') { var result = Find(handle, classCallback, textCallback); if (result != null) { CrashReason reason = CrashReason.Unknown; string text = result.Text; int i = text.IndexOf("Assertion:", 0, 100); if (i != -1) { int j = text.IndexOf('\n', i); if (text.IndexOf("Is your archive up to date?", i, j - i, StringComparison.OrdinalIgnoreCase) != -1 || text.IndexOf("Client needs to be patched", i, j - i, StringComparison.OrdinalIgnoreCase) != -1) { reason = CrashReason.PatchRequired; } } if (WindowCrashed != null) { WindowCrashed(this, reason); } } return; } else if (className.Equals(LAUNCHER_WINDOW_CLASSNAME)) { if (WindowChanged != null) { wce.Type = WindowChangedEventArgs.EventType.TitleChanged; WindowChanged(this, wce); } #region Find CoherentUI var pidChild = 0; var limit = DateTime.UtcNow.AddSeconds(30); do { if ((pidChild = GetChildProcess(process.Id)) > 0) { break; } this.process.Refresh(); if (_handle != this.process.MainWindowHandle) { break; } }while (DateTime.UtcNow < limit && !this.process.WaitForExit(500)); if (pidChild > 0) { try { using (var child = Process.GetProcessById(pidChild)) { limit = DateTime.UtcNow.AddSeconds(10); var pid = pidChild; do { if ((pidChild = GetChildProcess(pid)) > 0) { break; } this.process.Refresh(); if (_handle != this.process.MainWindowHandle) { break; } }while (DateTime.UtcNow < limit && !child.WaitForExit(500)); } if (pidChild > 0) { using (var child = Process.GetProcessById(pidChild)) { long mem = 0; byte counter = 0; limit = DateTime.UtcNow.AddSeconds(60); do { if (mem > 0) { child.Refresh(); } var _mem = child.PeakWorkingSet64; if (_mem > mem) { mem = _mem; counter = 0; } else if (++counter > 2) { break; } }while (DateTime.UtcNow < limit && !child.WaitForExit(100)); if (WindowChanged != null) { wce.Type = WindowChangedEventArgs.EventType.LauncherCoherentUIReady; WindowChanged(this, wce); } } } } catch (Exception ex) { Util.Logging.Log(ex); } } #endregion } } } } }while (!process.WaitForExit(500) && this.watcher != null); }
protected void OnFocusChange(WindowChangedEventArgs eventArgs) { FocusChange?.Invoke(this, eventArgs); }