static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) { //not stopping this might lead to even more errors KeyboardHookClass.DeleteKeyboardHook(); MouseHookClass.DeleteMouseHook(); GamepadHookClass.DestroyTimer(); if (e.Exception is ChainingException exception) { using (StreamWriter sw = File.AppendText(AppDataPath + "\\logs.log")) { sw.WriteLine(DateTime.Now.ToString(CultureInfo.InvariantCulture)); foreach (var cause in exception.GetExceptionChain()) { sw.WriteLine(cause); } sw.WriteLine("\n~~~~~~~~~~~~~~~~~~~\n~~~~~~~~~~~~~~~~~~~\n"); } } else { using (StreamWriter sw = File.AppendText(AppDataPath + "\\logs.log")) { sw.WriteLine(DateTime.Now.ToString(CultureInfo.InvariantCulture)); sw.WriteLine(e.Exception.Message); sw.WriteLine("\n~~~~~~~~~~~~~~~~~~~\n~~~~~~~~~~~~~~~~~~~\n"); } } MessageBox.Show("An exception occurred, for more info see the logs.", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error); Application.Exit(); }
/// <summary> /// verify if a gamepad is connected, if it is then check which buttons are pressed and the directions of the thumb sticks, /// if no gamepad is connected change the timer to 1 every 5 seconds /// </summary> /// <param name="sender"></param> /// <param name="eventArgs"></param> static void CheckGamepad(object?sender, EventArgs eventArgs) { try { //Console.WriteLine("checked for gamepad input"); switch (XInputGetState(0, out CurrentState)) { case ERROR_SUCCESS: { // if a controller was just connected go back to checking for input ~60 times per second if (frameTimer.Interval == 5000) { frameTimer.Interval = 15; } if (CurrentState.dwPacketNumber != LastState.dwPacketNumber) { var listOfButtonPresses = new List <string>(); //apply the bitmask for each button and take it as a press only if the result is not equal to 0 and if the previous state was equal to 0 if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) == 0) { listOfButtonPresses.Add("D_pad_up"); } if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) == 0) { listOfButtonPresses.Add("D_pad_down"); } if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) == 0) { listOfButtonPresses.Add("D_pad_right"); } if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) == 0) { listOfButtonPresses.Add("D_pad_left"); } if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_START) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_START) == 0) { listOfButtonPresses.Add("start"); } if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_BACK) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_BACK) == 0) { listOfButtonPresses.Add("back"); } if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) == 0) { listOfButtonPresses.Add("left_shoulder"); } if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) == 0) { listOfButtonPresses.Add("right_shoulder"); } if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) == 0) { listOfButtonPresses.Add("left_thumb"); } if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) == 0) { listOfButtonPresses.Add("right_thumb"); } if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_A) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_A) == 0) { listOfButtonPresses.Add("a"); } if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_B) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_B) == 0) { listOfButtonPresses.Add("b"); } if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_X) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_X) == 0) { listOfButtonPresses.Add("x"); } if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_Y) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_Y) == 0) { listOfButtonPresses.Add("y"); } if (CurrentState.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD && LastState.Gamepad.bLeftTrigger < XINPUT_GAMEPAD_TRIGGER_THRESHOLD) { listOfButtonPresses.Add("left_trigger"); } if (CurrentState.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD && LastState.Gamepad.bRightTrigger < XINPUT_GAMEPAD_TRIGGER_THRESHOLD) { listOfButtonPresses.Add("right_trigger"); } //take care of the cases where the absolute would underflow if (CurrentState.Gamepad.sThumbLY == short.MinValue) { CurrentState.Gamepad.sThumbLY = short.MinValue + 2; } if (CurrentState.Gamepad.sThumbLX == short.MinValue) { CurrentState.Gamepad.sThumbLX = short.MinValue + 2; } var directionL = MouseHookClass.MovementDirection( new Point(CurrentState.Gamepad.sThumbLX, CurrentState.Gamepad.sThumbLY), new Point(0, 0)); // update the direction of the left thumb stick only if it is outside of the dead zone and the previous state was inside the dead zone // or if the direction is different if ((Math.Abs(CurrentState.Gamepad.sThumbLY) > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE || Math.Abs(CurrentState.Gamepad.sThumbLX) > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) && !(Math.Abs(LastState.Gamepad.sThumbLY) > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE || Math.Abs(LastState.Gamepad.sThumbLX) > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) || (directionL != null && directionL != LastDirectionL)) { if (directionL != null) { listOfButtonPresses.Add("left_thumb_move_" + directionL); LastDirectionL = directionL; } } //take care of the cases where the absolute would underflow if (CurrentState.Gamepad.sThumbRY == short.MinValue) { CurrentState.Gamepad.sThumbRY = short.MinValue + 2; } if (CurrentState.Gamepad.sThumbRX == short.MinValue) { CurrentState.Gamepad.sThumbRX = short.MinValue + 2; } var directionR = MouseHookClass.MovementDirection( new Point(CurrentState.Gamepad.sThumbRX, CurrentState.Gamepad.sThumbRY), new Point(0, 0)); // update the direction of the right thumb stick only if it is outside of the dead zone and the previous state was inside the dead zone // or if the direction is different if ((Math.Abs(CurrentState.Gamepad.sThumbRX) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE || Math.Abs(CurrentState.Gamepad.sThumbRY) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) && !(Math.Abs(LastState.Gamepad.sThumbRX) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE || Math.Abs(LastState.Gamepad.sThumbRY) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) || (directionR != null && directionR != LastDirectionR)) { if (directionR != null) { listOfButtonPresses.Add("right_thumb_move_" + directionR); LastDirectionR = directionR; } } if (listOfButtonPresses.Count > 0) { ProfileManager.GamepadInputUpdate(listOfButtonPresses); } LastState = CurrentState; } break; } case ERROR_DEVICE_NOT_CONNECTED: { // if no gamepad is connected then search for input only once every 5 seconds if (frameTimer.Interval != 5000) { frameTimer.Interval = 5000; } break; } } } catch (Exception e) { if (e is ChainingException exception) { exception.AddErrorToChain("While trying to read gamepad input"); } else { exception = new ChainingException(e.Message); exception.AddErrorToChain("While trying to read gamepad input"); } throw exception; } }
static void Main() { using (Mutex mutex = new Mutex(true, "KeyCounter", out bool createNew)) { if (createNew) { if (!Directory.Exists(AppDataPath)) { Directory.CreateDirectory(AppDataPath); } Application.EnableVisualStyles(); Application.SetHighDpiMode(Application.HighDpiMode); Application.SetCompatibleTextRenderingDefault(false); Application.ThreadException += Application_ThreadException; Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); AppDomain.CurrentDomain.UnhandledException += Application_UnhandledException; // while the other 2 handlers catch almost all exceptions this is the only way of getting the ones when the keyCounterMainFrame_frame fails to initialize try { MainFrame = new keyCounterMainFrame_frame(); Application.Run(MainFrame); } catch (Exception e) { //not stopping this might lead to even more errors KeyboardHookClass.DeleteKeyboardHook(); MouseHookClass.DeleteMouseHook(); GamepadHookClass.DestroyTimer(); if (e is ChainingException exception) { using (StreamWriter sw = File.AppendText(AppDataPath + "\\logs.log")) { sw.WriteLine(DateTime.Now.ToString(CultureInfo.InvariantCulture)); foreach (var cause in exception.GetExceptionChain()) { sw.WriteLine(cause); } sw.WriteLine("\n~~~~~~~~~~~~~~~~~~~\n~~~~~~~~~~~~~~~~~~~\n"); } } else { using (StreamWriter sw = File.AppendText(AppDataPath + "\\logs.log")) { var ex = e; sw.WriteLine(DateTime.Now.ToString(CultureInfo.InvariantCulture)); if (ex != null) { sw.WriteLine(ex.Message); } sw.WriteLine("\n~~~~~~~~~~~~~~~~~~~\n~~~~~~~~~~~~~~~~~~~\n"); } } MessageBox.Show("An exception occurred, for more info see the logs.", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error); Application.Exit(); } } else { Process current = Process.GetCurrentProcess(); foreach (Process process in Process.GetProcessesByName(current.ProcessName)) { if (process.Id != current.Id) { MessageBox.Show("There already is an instance of this app running."); break; } } } } }