private void AttachButton_Click(object aObj, System.Windows.RoutedEventArgs aEvent)
        {
            AttachButton.IsEnabled  = false;
            RefreshButton.IsEnabled = false;
            if (!_attached)
            {
                var process  = ProcessListBox.SelectedItems.Cast <ProcessInfo>().ToList();
                var attached = false;
                if (process[0].CanUseMono)
                {
                    _unityMod = new UnityVRMod();
                    _unityMod.MessageReceivedHandler += OnMessageReceived;
                    _unityMod.Inject(process[0].Id, process[0].FrameworkVersion, process[0].MonoModule);
                    attached = true;
                }

                if (process[0].CanUseXInput)
                {
                    _xinputMod = new XInputMod();
                    _xinputMod.Attach(process[0].Id);
                    _xinputMod.MessageReceivedHandler += OnMessageReceived;
                    attached = true;
                }

                if (attached)
                {
                    ProcessAttached?.Invoke(this, null);
                }
            }
            else
            {
                ProcessDetached?.Invoke(this, null);
                Detach();
            }
        }
        private void EnumProcesses()
        {
            Dispatcher.Invoke(() => { _processList.Clear(); });
            Dispatcher.Invoke(() => { ProcessStatus = "Scanning Processes..."; });
            var cp = Process.GetCurrentProcess().Id;
            const ProcessAccessRights flags = ProcessAccessRights.PROCESS_QUERY_INFORMATION | ProcessAccessRights.PROCESS_VM_READ;
            var procList = from proc in Process.GetProcesses() orderby proc.ProcessName select proc;

            Parallel.ForEach(procList, (currentProc) =>
            {
                if (_scanningToken.IsCancellationRequested)
                {
                    return;
                }
                var handle = IntPtr.Zero;

                try
                {
                    // This can sometimes happen between calling GetProcesses and getting here. Save ourselves the throw.
                    if (currentProc.HasExited || currentProc.Id == cp)
                    {
                        return;
                    }

                    // This is usually what throws, so do it before we invoke via dispatcher.
                    var owner = RemoteHooking.GetProcessIdentity(currentProc.Id).Name;

                    if ((handle = Native.OpenProcess(flags, false, currentProc.Id)) == IntPtr.Zero)
                    {
                        return;
                    }

                    var procInfo = new ProcessInfo
                    {
                        FileName = currentProc.ProcessName,
                        Id       = currentProc.Id,
                    };

                    if (XInputMod.CanUseMod(handle))
                    {
                        procInfo.Owner = owner;
                    }

                    if (UnityVRMod.CanUseMod(handle, currentProc.MainModule.FileName, out var module, out var frameworkVersion))
                    {
                        procInfo.MonoModule       = module;
                        procInfo.FrameworkVersion = frameworkVersion;
                    }

                    if (procInfo.CanUseXInput || procInfo.CanUseMono)
                    {
                        Dispatcher.Invoke(() =>
                        {
                            _log.Debug(procInfo);
                            _processList.Add(procInfo);
                        });
                    }
                }
        private void EnumProcesses()
        {
            Dispatcher.Invoke(() => { _processList.Clear(); });
            Dispatcher.Invoke(() => { ProcessError = "Scanning Processes..."; });
            var cp = Process.GetCurrentProcess().Id;
            const ProcessAccessRights flags = ProcessAccessRights.PROCESS_QUERY_INFORMATION | ProcessAccessRights.PROCESS_VM_READ;

            foreach (var currentProc in from proc in Process.GetProcesses() orderby proc.ProcessName select proc)
            {
                var handle = IntPtr.Zero;

                try
                {
                    // This can sometimes happen between calling GetProcesses and getting here. Save ourselves the throw.
                    if (currentProc.HasExited || currentProc.Id == cp)
                    {
                        continue;
                    }

                    // This is usually what throws, so do it before we invoke via dispatcher.
                    var owner = RemoteHooking.GetProcessIdentity(currentProc.Id).Name;

                    if ((handle = Native.OpenProcess(flags, false, currentProc.Id)) == IntPtr.Zero)
                    {
                        continue;
                    }

                    var procInfo = new ProcessInfo
                    {
                        FileName = currentProc.ProcessName,
                        Id       = currentProc.Id,
                    };

                    if (XInputMod.CanUseMod(handle))
                    {
                        procInfo.Owner = owner;
                    }

                    if (UnityVRMod.CanUseMod(handle, currentProc.MainModule.FileName, out var module, out var frameworkVersion))
                    {
                        procInfo.MonoModule       = module;
                        procInfo.FrameworkVersion = frameworkVersion;
                    }

                    if (procInfo.CanUseXInput || procInfo.CanUseMono)
                    {
                        Dispatcher.Invoke(() =>
                        {
                            _log.Debug(procInfo);
                            _processList.Add(procInfo);
                        });
                    }
                }
                catch (AccessViolationException)
                {
                    // noop, there's a lot of system processes we can't see.
                }
                catch (Win32Exception)
                {
                    // noop, there's a lot of system processes we can't see.
                }
                catch (Exception aEx)
                {
                    _log.Error(aEx);
                }
                finally
                {
                    // Only close the
                    if (handle != IntPtr.Zero)
                    {
                        Native.CloseHandle(handle);
                    }
                }
            }
            Dispatcher.Invoke(() => { ProcessError = "Select Process to Inject"; });
            _enumProcessTask = null;
        }