/// <summary>
        /// 向 Textractor 写入命令
        /// 根据 TextHookHeadData 的集合卸载这些集合之外的其它同进程 Hook
        /// 并删除文本储存字典中相应的键值
        /// </summary>
        /// <param name="textHookData">TextHookHeadData 的集合</param>
        /// <returns></returns>
        public async Task DetachProcessByTextHookData(IEnumerable <TextHookData> textHookData)
        {
            // 按 ProcessID 分组
            var query = textHookData
                        .GroupBy(item => item.HeadData.ProcessID);

            // 按组处理
            foreach (var item in query)
            {
                // 找出符合条件的
                var query2 = TextractorOutPutDic.Keys
                             .Where(itemA => itemA.ProcessID == item.Key && item.All(itemB => itemB.HeadData.Address != itemA.Address));
                // 按 Address 去重
                var query3 = query2
                             .GroupBy(item => item.Address)
                             .Select(item => item.First());
                // Detach Hook
                foreach (var item2 in query3)
                {
                    await DetachProcessByTextHookHeadData(item2);
                }
                // 删除文本储存字典中相应的键值
                // 为啥没报错是因为:https://docs.microsoft.com/zh-cn/dotnet/api/system.collections.generic.dictionary-2.enumerator?view=net-6.0
                foreach (var item2 in query2)
                {
                    TextractorOutPutDic.Remove(item2);
                }
            }
        }
        /// <summary>
        /// 向 Textractor 写入命令
        /// 卸载所有的 Hook
        /// </summary>
        /// <returns></returns>
        public async Task DetachAllProcess()
        {
            var query = TextractorOutPutDic.Keys
                        .Where(item => item.ProcessID > 0)
                        .Select(item => item.ProcessID)
                        .Distinct();

            foreach (var item in query)
            {
                await DetachProcess(item);
            }
            TextractorOutPutDic.Clear(); // TODO 与 Destroy 重复
        }
        /// <summary>
        /// 关闭 Textractor 进程,关闭前 Detach 所有 Hook
        /// </summary>
        public async void Destroy()
        {
            if (TextractorProcess != null && TextractorProcess.HasExited == false)
            {
                await DetachAllProcess();

                TextractorProcess.Kill();
            }
            TextractorProcess?.Dispose();
            TextractorProcess = null;

            TextOutputEvent = null;
            TextractorOutPutDic.Clear();
            IsPause = false;
        }
        private void OutputHandler(object sender, DataReceivedEventArgs e)
        {
#if DEBUG
            Trace.TraceInformation("OutputHandler: " + e.Data);
#endif

            if (IsPause || e.Data == null || !e.Data.StartsWith("["))
            {
                return;
            }

            // 解析数据生成对象
            TextHookData textHookData;
            try {
                textHookData = new(e.Data); // TODO 一行中多条信息 FactoryMode return array
            } catch (Exception ex) {
                Trace.TraceError(ex.Message);
                return;
            }

            // 加入到文本储存字典
            if (!TextractorOutPutDic.ContainsKey(textHookData.HeadData))
            {
                TextractorOutPutDic.Add(textHookData.HeadData, textHookData);
            }
            else
            {
                TextractorOutPutDic[textHookData.HeadData] = textHookData;
            }

            // 调用外部事件
            TextOutputEvent?.Invoke(textHookData);

#if DEBUG
            Trace.TraceInformation("OutputHandler: " + textHookData.TextData);
#endif
        }