diff --git a/.vs/AIProofread/v17/.suo b/.vs/AIProofread/v17/.suo index 835cfbd..d4d7a03 100644 Binary files a/.vs/AIProofread/v17/.suo and b/.vs/AIProofread/v17/.suo differ diff --git a/AIProofread/AIProofread.csproj b/AIProofread/AIProofread.csproj index e08abca..ae7b7c0 100644 --- a/AIProofread/AIProofread.csproj +++ b/AIProofread/AIProofread.csproj @@ -373,6 +373,7 @@ + diff --git a/AIProofread/Bridge.cs b/AIProofread/Bridge.cs index 0449052..ae17d92 100644 --- a/AIProofread/Bridge.cs +++ b/AIProofread/Bridge.cs @@ -7,6 +7,7 @@ using Microsoft.Office.Tools.Word; using Microsoft.Web.WebView2.Core; using Microsoft.Web.WebView2.WinForms; using Newtonsoft.Json; +using NPOI; using NPOI.SS.Formula; using NPOI.XSSF.UserModel; using NPOI.XWPF.UserModel; @@ -46,7 +47,7 @@ namespace AIProofread public static Dictionary marks; - private static int selectProofreadId = -1; + //private static int selectProofreadId = -1; private static object missing = System.Reflection.Missing.Value; @@ -246,6 +247,8 @@ namespace AIProofread ProcessStartInfo processStartInfo = new ProcessStartInfo(Path.Combine(applicationBase, Path.GetFileName(path))) { WorkingDirectory = applicationBase, + UseShellExecute = true, + Verb="runas" }; Process.Start(processStartInfo); } @@ -336,12 +339,12 @@ namespace AIProofread if (ShouldUpgradeForced()) { data.Add("code", 2); - data.Add("message", "请升级插件后再进行校对"); + data.Add("message", "请先升级插件后再进行校对"); } else if (doc.ProtectionType != WdProtectionType.wdNoProtection) { data.Add("code", 3); - data.Add("message", "文档受保护,无法编辑"); + data.Add("message", "文档受保护,请另存文档后再进行校对"); } else if (doc.ReadOnly) { @@ -369,7 +372,22 @@ namespace AIProofread data.Add("documentId", GeIdBytDocument(doc)); data.Add("wordsCount", doc.Words.Count); data.Add("charactersCount", doc.Characters.Count); - data.Add("content", Tools.GetAllText(doc)); + try + { + + data.Add("content", Tools.GetAllText(doc)); + } + catch (POIXMLException ex) + { + Logger.Log(ex); + data["code"] = 5; + data["message"] = "文档格式有误,请另存文档后再进行校对"; + } + catch (Exception ex) + { + Logger.Log(ex); + throw ex; + } //if (loadingDialog != null && !loadingDialog.IsDisposed) //{ // loadingDialog.Close(); @@ -751,6 +769,7 @@ namespace AIProofread } catch (Exception ex) { + Logger.Log("导出勘误表失败:" + ex.Message + "\n" + ex.StackTrace + "\n\n"); return BridgeResult.Error(-1, ex.Message); } } diff --git a/AIProofread/Config.cs b/AIProofread/Config.cs index d4a1ff1..4172a7b 100644 --- a/AIProofread/Config.cs +++ b/AIProofread/Config.cs @@ -12,7 +12,7 @@ namespace AIProofread public class Config { public static readonly string APP_NAME = "AI校对王"; - public static readonly string APP_VERSION = "2.2.1"; + public static readonly string APP_VERSION = "2.2.2"; public static bool IS_WPS = false; public static bool UpgradeForcedNotice = false; public static readonly string APP_BASE_DIR = AppDomain.CurrentDomain.BaseDirectory; diff --git a/AIProofread/Controls/FormContact.Designer.cs b/AIProofread/Controls/FormContact.Designer.cs index 8a52482..19e0dc1 100644 --- a/AIProofread/Controls/FormContact.Designer.cs +++ b/AIProofread/Controls/FormContact.Designer.cs @@ -40,7 +40,7 @@ this.WebViewContact.Dock = System.Windows.Forms.DockStyle.Fill; this.WebViewContact.Location = new System.Drawing.Point(0, 0); this.WebViewContact.Name = "WebViewContact"; - this.WebViewContact.Size = new System.Drawing.Size(540, 420); + this.WebViewContact.Size = new System.Drawing.Size(620, 450); this.WebViewContact.TabIndex = 0; this.WebViewContact.ZoomFactor = 1D; // @@ -48,7 +48,7 @@ // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(540, 420); + this.ClientSize = new System.Drawing.Size(620, 450); this.Controls.Add(this.WebViewContact); this.Name = "FormContact"; this.ShowIcon = false; diff --git a/AIProofread/Controls/FormLogger.cs b/AIProofread/Controls/FormLogger.cs index 387a54b..094fba8 100644 --- a/AIProofread/Controls/FormLogger.cs +++ b/AIProofread/Controls/FormLogger.cs @@ -5,7 +5,7 @@ namespace AIProofread.Controls { public partial class FormLogger : Form { - private ListView LogListView; + private ListView LogListView = new ListView(); public FormLogger() { diff --git a/AIProofread/Logger.cs b/AIProofread/Logger.cs index f13c67e..3ee9048 100644 --- a/AIProofread/Logger.cs +++ b/AIProofread/Logger.cs @@ -23,7 +23,6 @@ namespace AIProofread if (LoggerForm != null && !LoggerForm.IsDisposed && LoggerForm.Visible) { LoggerForm.Log(time, tag, message); - return; } string path = Config.APP_LOG_PATH + DateTime.Now.ToString("yyyy-MM-dd") + ".txt"; if (!Directory.Exists(Config.APP_LOG_PATH)) @@ -41,7 +40,7 @@ namespace AIProofread streamWriter.Close(); streamWriter.Dispose(); } - catch (Exception e) { } + catch (Exception) { } } public static void Log(string msg) { diff --git a/AIProofread/Model/DocumentInfo.cs b/AIProofread/Model/DocumentInfo.cs index 14d5e56..882686c 100644 --- a/AIProofread/Model/DocumentInfo.cs +++ b/AIProofread/Model/DocumentInfo.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Drawing; using System.IO; +using System.Runtime.InteropServices; using System.Threading; using System.Windows.Forms; using AIProofread.Controls; @@ -158,7 +159,7 @@ namespace AIProofread.Model private void ShowDocumentStatus(string tag) { - Logger.Log($"{fileName} {tag} PaneVisible is {PaneVisible} Poofread is {Proofread} Proofreading is {Proofreading}"); + // Logger.Log($"{fileName} {tag} PaneVisible is {PaneVisible} Poofread is {Proofread} Proofreading is {Proofreading}"); } /// @@ -211,6 +212,12 @@ namespace AIProofread.Model { try { + // 释放com + try + { + Marshal.ReleaseComObject(CurrentDocument); + } + catch (Exception) { } if(TaskPane.Control.IsDisposed) return; ProofreadMainControl control = (ProofreadMainControl)TaskPane.Control; control.ResetWeb(); @@ -647,7 +654,7 @@ namespace AIProofread.Model foreach (var item in correct.CorrectItems) { if (marks.ContainsKey(item.Id)) continue; - Logger.Log(string.Format("mark type {0} data {1}->{2}", item.Tag, item.Origin, item.Text)); + // Logger.Log(string.Format("mark type {0} data {1}->{2}", item.Tag, item.Origin, item.Text)); int _prev = prevOffset; bool isDisabled = false; // 判断查找内容是否在原始数据中,否则直跳过 @@ -773,7 +780,7 @@ namespace AIProofread.Model pi.originBackgroundColor = info.Background; pi.originSize = info.Size; } - catch (Exception ex) { } + catch (Exception ex) { Logger.Log(ex); } } marks.Add(item.Id, pi); } @@ -888,7 +895,7 @@ namespace AIProofread.Model TaskPane.Control.Focus(); } - internal void Close() + public void Close() { try { @@ -896,7 +903,8 @@ namespace AIProofread.Model marks.Clear(); // 清除区域相关数据 ranges.Clear(); - TaskPane.Dispose(); + // TaskPane.Dispose(); + this.Dispose(); } catch (Exception ex) { @@ -912,7 +920,7 @@ namespace AIProofread.Model })); } - internal void ShowUpgrade(string data, bool force) + public void ShowUpgrade(string data, bool force) { TaskPane.Control.BeginInvoke(new Action(() => { @@ -922,6 +930,7 @@ namespace AIProofread.Model if (force) { + // 已经强制更新但被忽略过则不再提示 if (Config.UpgradeForcedNotice) return; var result = MessageBox.Show(upgradeData.Message, "是否确认更新", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question); @@ -1009,5 +1018,11 @@ namespace AIProofread.Model } return dic; } + + internal void CheckPanel() + { + Logger.Log(CurrentDocument.FullName + $" TaskPane visible {PaneVisible} has " + (TaskPane == null ? "null" : "exists")); + if (TaskPane == null) CreateTaskPane(); + } } } diff --git a/AIProofread/Model/ExportDataItem.cs b/AIProofread/Model/ExportDataItem.cs index df15677..d28a47b 100644 --- a/AIProofread/Model/ExportDataItem.cs +++ b/AIProofread/Model/ExportDataItem.cs @@ -50,7 +50,7 @@ namespace AIProofread.Model return originText; } } - catch (Exception ex) { } + catch (Exception ex) { Logger.Log(ex); } var range = item.mark.Range; // 获取range所在句子 diff --git a/AIProofread/Ribbon1.Designer.cs b/AIProofread/Ribbon1.Designer.cs index 6d61c94..9e8b2a8 100644 --- a/AIProofread/Ribbon1.Designer.cs +++ b/AIProofread/Ribbon1.Designer.cs @@ -41,13 +41,6 @@ namespace AIProofread Microsoft.Office.Tools.Ribbon.RibbonDropDownItem ribbonDropDownItemImpl3 = this.Factory.CreateRibbonDropDownItem(); this.tabAIProofread = this.Factory.CreateRibbonTab(); this.group1 = this.Factory.CreateRibbonGroup(); - this.Group = this.Factory.CreateRibbonGroup(); - this.grpOther = this.Factory.CreateRibbonGroup(); - this.LblDate = this.Factory.CreateRibbonLabel(); - this.LblNickname = this.Factory.CreateRibbonLabel(); - this.group2 = this.Factory.CreateRibbonGroup(); - this.grpDebug = this.Factory.CreateRibbonGroup(); - this.dropDown1 = this.Factory.CreateRibbonDropDown(); this.BtnProofreadAll = this.Factory.CreateRibbonButton(); this.menuProofreadList = this.Factory.CreateRibbonMenu(); this.BtnProofreadExact = this.Factory.CreateRibbonButton(); @@ -60,14 +53,20 @@ namespace AIProofread this.btnDetectionParagraph = this.Factory.CreateRibbonButton(); this.btnDetectionHistory = this.Factory.CreateRibbonButton(); this.btnSetting = this.Factory.CreateRibbonButton(); + this.Group = this.Factory.CreateRibbonGroup(); this.ButtonSaveCache = this.Factory.CreateRibbonButton(); this.ButtonLoadCache = this.Factory.CreateRibbonButton(); + this.grpOther = this.Factory.CreateRibbonGroup(); this.BtnGetContact = this.Factory.CreateRibbonButton(); this.BtnUpdate = this.Factory.CreateRibbonButton(); this.btnLogin = this.Factory.CreateRibbonButton(); this.btnLogout = this.Factory.CreateRibbonButton(); + this.LblDate = this.Factory.CreateRibbonLabel(); + this.LblNickname = this.Factory.CreateRibbonLabel(); + this.group2 = this.Factory.CreateRibbonGroup(); this.BtnShowPanel = this.Factory.CreateRibbonButton(); this.BtnShowManual = this.Factory.CreateRibbonButton(); + this.grpDebug = this.Factory.CreateRibbonGroup(); this.btnShowPane = this.Factory.CreateRibbonButton(); this.btnHidePane = this.Factory.CreateRibbonButton(); this.BtnOpenLog = this.Factory.CreateRibbonButton(); @@ -76,6 +75,7 @@ namespace AIProofread this.BtnTest = this.Factory.CreateRibbonButton(); this.BtnOpenAppDir = this.Factory.CreateRibbonButton(); this.BtnShowVersion = this.Factory.CreateRibbonButton(); + this.dropDown1 = this.Factory.CreateRibbonDropDown(); this.tabAIProofread.SuspendLayout(); this.group1.SuspendLayout(); this.Group.SuspendLayout(); @@ -106,66 +106,6 @@ namespace AIProofread this.group1.Items.Add(this.btnSetting); this.group1.Name = "group1"; // - // Group - // - this.Group.Items.Add(this.ButtonSaveCache); - this.Group.Items.Add(this.ButtonLoadCache); - this.Group.Name = "Group"; - // - // grpOther - // - this.grpOther.Items.Add(this.BtnGetContact); - this.grpOther.Items.Add(this.BtnUpdate); - this.grpOther.Items.Add(this.btnLogin); - this.grpOther.Items.Add(this.btnLogout); - this.grpOther.Items.Add(this.LblDate); - this.grpOther.Items.Add(this.LblNickname); - this.grpOther.Name = "grpOther"; - // - // LblDate - // - this.LblDate.Label = "过期时间:"; - this.LblDate.Name = "LblDate"; - this.LblDate.Visible = false; - // - // LblNickname - // - this.LblNickname.Label = "xxx 已登录"; - this.LblNickname.Name = "LblNickname"; - this.LblNickname.Visible = false; - // - // group2 - // - this.group2.Items.Add(this.BtnShowPanel); - this.group2.Items.Add(this.BtnShowManual); - this.group2.Name = "group2"; - // - // grpDebug - // - this.grpDebug.Items.Add(this.btnShowPane); - this.grpDebug.Items.Add(this.btnHidePane); - this.grpDebug.Items.Add(this.BtnOpenLog); - this.grpDebug.Items.Add(this.button1); - this.grpDebug.Items.Add(this.BtnOpenLogger); - this.grpDebug.Items.Add(this.BtnTest); - this.grpDebug.Items.Add(this.BtnOpenAppDir); - this.grpDebug.Items.Add(this.BtnShowVersion); - this.grpDebug.Items.Add(this.dropDown1); - this.grpDebug.Label = "开发调试"; - this.grpDebug.Name = "grpDebug"; - this.grpDebug.Visible = false; - // - // dropDown1 - // - ribbonDropDownItemImpl1.Label = "开发"; - ribbonDropDownItemImpl2.Label = "测试"; - ribbonDropDownItemImpl3.Label = "生产"; - this.dropDown1.Items.Add(ribbonDropDownItemImpl1); - this.dropDown1.Items.Add(ribbonDropDownItemImpl2); - this.dropDown1.Items.Add(ribbonDropDownItemImpl3); - this.dropDown1.Label = "环境"; - this.dropDown1.Name = "dropDown1"; - // // BtnProofreadAll // this.BtnProofreadAll.ControlSize = Microsoft.Office.Core.RibbonControlSize.RibbonControlSizeLarge; @@ -270,6 +210,12 @@ namespace AIProofread this.btnSetting.ShowImage = true; this.btnSetting.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(this.btnSetting_Click); // + // Group + // + this.Group.Items.Add(this.ButtonSaveCache); + this.Group.Items.Add(this.ButtonLoadCache); + this.Group.Name = "Group"; + // // ButtonSaveCache // this.ButtonSaveCache.ControlSize = Microsoft.Office.Core.RibbonControlSize.RibbonControlSizeLarge; @@ -288,6 +234,16 @@ namespace AIProofread this.ButtonLoadCache.ShowImage = true; this.ButtonLoadCache.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(this.ButtonLoadCache_Click); // + // grpOther + // + this.grpOther.Items.Add(this.BtnGetContact); + this.grpOther.Items.Add(this.BtnUpdate); + this.grpOther.Items.Add(this.btnLogin); + this.grpOther.Items.Add(this.btnLogout); + this.grpOther.Items.Add(this.LblDate); + this.grpOther.Items.Add(this.LblNickname); + this.grpOther.Name = "grpOther"; + // // BtnGetContact // this.BtnGetContact.ControlSize = Microsoft.Office.Core.RibbonControlSize.RibbonControlSizeLarge; @@ -325,6 +281,24 @@ namespace AIProofread this.btnLogout.Visible = false; this.btnLogout.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(this.btnLogout_Click); // + // LblDate + // + this.LblDate.Label = "过期时间:"; + this.LblDate.Name = "LblDate"; + this.LblDate.Visible = false; + // + // LblNickname + // + this.LblNickname.Label = "xxx 已登录"; + this.LblNickname.Name = "LblNickname"; + this.LblNickname.Visible = false; + // + // group2 + // + this.group2.Items.Add(this.BtnShowPanel); + this.group2.Items.Add(this.BtnShowManual); + this.group2.Name = "group2"; + // // BtnShowPanel // this.BtnShowPanel.ControlSize = Microsoft.Office.Core.RibbonControlSize.RibbonControlSizeLarge; @@ -343,6 +317,21 @@ namespace AIProofread this.BtnShowManual.ShowImage = true; this.BtnShowManual.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(this.BtnShowManual_Click); // + // grpDebug + // + this.grpDebug.Items.Add(this.btnShowPane); + this.grpDebug.Items.Add(this.btnHidePane); + this.grpDebug.Items.Add(this.BtnOpenLog); + this.grpDebug.Items.Add(this.button1); + this.grpDebug.Items.Add(this.BtnOpenLogger); + this.grpDebug.Items.Add(this.BtnTest); + this.grpDebug.Items.Add(this.BtnOpenAppDir); + this.grpDebug.Items.Add(this.BtnShowVersion); + this.grpDebug.Items.Add(this.dropDown1); + this.grpDebug.Label = "开发调试"; + this.grpDebug.Name = "grpDebug"; + this.grpDebug.Visible = false; + // // btnShowPane // this.btnShowPane.Label = "显示面板"; @@ -391,6 +380,17 @@ namespace AIProofread this.BtnShowVersion.Name = "BtnShowVersion"; this.BtnShowVersion.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(this.BtnShowVersion_Click); // + // dropDown1 + // + ribbonDropDownItemImpl1.Label = "开发"; + ribbonDropDownItemImpl2.Label = "测试"; + ribbonDropDownItemImpl3.Label = "生产"; + this.dropDown1.Items.Add(ribbonDropDownItemImpl1); + this.dropDown1.Items.Add(ribbonDropDownItemImpl2); + this.dropDown1.Items.Add(ribbonDropDownItemImpl3); + this.dropDown1.Label = "环境"; + this.dropDown1.Name = "dropDown1"; + // // Ribbon1 // this.Name = "Ribbon1"; diff --git a/AIProofread/Ribbon1.cs b/AIProofread/Ribbon1.cs index b4caa35..85174ef 100644 --- a/AIProofread/Ribbon1.cs +++ b/AIProofread/Ribbon1.cs @@ -18,7 +18,6 @@ namespace AIProofread public partial class Ribbon1 { private bool IS_LOGIN = false; - private static bool IS_WPS = false; private Userinfo currentLoginUserinfo; private void Ribbon1_Load(object sender, RibbonUIEventArgs e) @@ -71,6 +70,7 @@ namespace AIProofread else if (key == "disable-by-upgrade") { SetCommonBtnStatus(status); + BtnUpdate.Enabled = true; BtnShowPanel.Enabled = status; } } @@ -80,7 +80,6 @@ namespace AIProofread /// public void InitWPS() { - IS_WPS = true; BtnProofreadAll.Image = AIProofread.Properties.Resources.icon_proofread_wps; menuProofreadList.Image = AIProofread.Properties.Resources.icon_proofread_wps; @@ -630,11 +629,14 @@ namespace AIProofread private void BtnProofreadExact_Click(object sender, RibbonControlEventArgs e) { + // + Globals.ThisAddIn.ActiveDocument.CheckPanel(); Globals.ThisAddIn.SendMessageToWeb("start", "exact"); } private void BtnProofreadFull_Click(object sender, RibbonControlEventArgs e) { + Globals.ThisAddIn.ActiveDocument.CheckPanel(); Globals.ThisAddIn.SendMessageToWeb("start", "full"); } } diff --git a/AIProofread/ThisAddIn.cs b/AIProofread/ThisAddIn.cs index e6263a9..6840c63 100644 --- a/AIProofread/ThisAddIn.cs +++ b/AIProofread/ThisAddIn.cs @@ -10,6 +10,7 @@ using AIProofread.Model; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading.Tasks; +using System.Text; //using CustomTaskPane = Microsoft.Office.Core.CustomTaskPane; //using CustomTaskPane = Microsoft.Office.Tools.CustomTaskPane; //using NPOI.SS.Formula.Functions; @@ -122,8 +123,8 @@ namespace AIProofread Application.WindowActivate += Application_WindowActivate; //Application.WindowDeactivate += Application_WindowDeactivate; - Application.DocumentBeforeSave += Application_DocumentBeforeSave; ; - + Application.DocumentBeforeSave += Application_DocumentBeforeSave; + (Application as ApplicationEvents4_Event).NewDocument += Application_NewDocument; Application.DocumentChange += Application_DocumentChange; // 选区发生变化事件 @@ -139,7 +140,7 @@ namespace AIProofread } catch (Exception ex1) { - Logger.Log("Startup", ex1.ToString()); + Logger.Log("Startup Error" + ex1.ToString()); } } @@ -163,7 +164,7 @@ namespace AIProofread } catch (Exception ex) { - Logger.Log("InitDeviceId", ex.ToString()); + Logger.Log("InitDeviceId Error:" + ex.ToString()); } }); } @@ -172,24 +173,30 @@ namespace AIProofread public void CheckDocumentClosed(object sender, System.Timers.ElapsedEventArgs e) { var existsList = new List(); - Logger.Log("检测文档是否关闭 ..."); try { - if (documentList.Count == 0) return; - + var docList = CurrentWordApplication.Documents; + if (documentList.Count == 0 || docList.Count == existsList.Count) return; existsList.Clear(); - - foreach (Document item in CurrentWordApplication.Documents) + foreach (Document item in docList) { existsList.Add(item.FullName); } + // 检测文档是否关闭 for (int i = documentList.documentList.Count - 1; i >= 0; i--) { var item = documentList.documentList[i]; - if (!existsList.Contains(item.fileName)) + // 可能出现另存问题 所以需要更新文件名称 + var oldName = item.fileName; + var currentName = item.CurrentDocument.FullName; + if(oldName != currentName) { - Logger.Log("检测到文档关闭,已移除:" + item.fileName); + item.fileName = currentName; + } + if (!existsList.Contains(currentName)) + { + Logger.Log("检测到文档关闭,已移除:" + currentName); try { item.RunInMainThread(() => @@ -340,7 +347,7 @@ namespace AIProofread // 设置当前文档 ActiveDocument = documentList.SetActiveDocument(CurrentWordApplication.ActiveDocument); ActiveDocument.CheckBtnStatus(); - CheckDocumentClosed(null,null); + CheckDocumentClosed(null, null); Logger.Log("Application_DocumentChange -- " + ActiveDocument.fileName); } @@ -426,12 +433,12 @@ namespace AIProofread private void Application_NewDocument(Document doc) { - Logger.Log("NewDocument", doc.Name); + Logger.Log("NewDocument" + doc.Name); } private void Application_DocumentOpen(Document doc) { - Logger.Log("DocumentOpen", doc.Name); + Logger.Log("DocumentOpen " + doc.Name); } diff --git a/AIProofread/core/DocumentReader.cs b/AIProofread/core/DocumentReader.cs new file mode 100644 index 0000000..37474cb --- /dev/null +++ b/AIProofread/core/DocumentReader.cs @@ -0,0 +1,76 @@ +using System.Runtime.InteropServices; +using System.Windows.Forms; +using System; +using Word = Microsoft.Office.Interop.Word; +using System.Collections.Generic; + +namespace AIProofread.core +{ + public class ProcessingContext + { + public Word.Range Range { get; set; } + public int GlobalIndex { get; set; } + } + public class DocumentReader + { + private static readonly Stack _processingStack = new Stack(); + public static List ReadByVSTO(Word.Document _doc, Word.Application _app, List list) + { + //List list = new List(); + try + { + // 关闭屏幕更新 + _app.ScreenUpdating = false; + + // 初始化堆栈:处理所有顶级 StoryRanges + foreach (Word.Range storyRange in _doc.StoryRanges) + { + _processingStack.Push(new ProcessingContext + { + Range = storyRange, + GlobalIndex = 0, + }); + } + + // 迭代处理堆栈中的每个 Range + while (_processingStack.Count > 0) + { + var context = _processingStack.Pop(); + ProcessElement(context.Range, context.GlobalIndex, list); + Marshal.ReleaseComObject(context.Range); + } + } + catch (Exception ex) + { + MessageBox.Show(ex.Message); + } + finally + { + _app.ScreenUpdating = true; + Marshal.ReleaseComObject(_doc); + } + return list; + } + private static void ProcessElement(Word.Range range, int globalIndex, List list) + { + if (range.Text?.Trim() == "\r\a") + { + globalIndex++; + return; + } + var paragraphs = range.Paragraphs; + // Debug.WriteLine($"Processing element: {range.Text}"); + // 处理段落 + foreach (Word.Paragraph paragraph in paragraphs) + { + list.Add(new DocumentText + { + Text = paragraph.Range.Text, + ParagraphNumber = globalIndex + 1 + }); + Marshal.ReleaseComObject(paragraph); + globalIndex++; + } + } + } +} diff --git a/AIProofread/core/DocumentUtil.cs b/AIProofread/core/DocumentUtil.cs index c336de6..e418f2d 100644 --- a/AIProofread/core/DocumentUtil.cs +++ b/AIProofread/core/DocumentUtil.cs @@ -600,7 +600,7 @@ namespace AIProofread // 判断原始文件是否可以删除 if (File.GetAttributes(sfd.FileName).HasFlag(FileAttributes.ReadOnly)) { - Globals.ThisAddIn.ShowDialog("已经存在名勘误表文件,请更换名称或者手动删除", null, null); + Globals.ThisAddIn.ShowDialog("已经存在名勘误表文件,请更换名称或手动删除", null, null); return; } // 删除文件 重新写入新数据避免出现未知不可控bug diff --git a/AIProofread/core/Tools.cs b/AIProofread/core/Tools.cs index 4d0a47b..29c642b 100644 --- a/AIProofread/core/Tools.cs +++ b/AIProofread/core/Tools.cs @@ -1,11 +1,14 @@ -using Microsoft.Office.Interop.Word; +using AIProofread.core; +using Microsoft.Office.Interop.Word; using Newtonsoft.Json; +using NPOI; using NPOI.POIFS.FileSystem; using NPOI.XWPF.UserModel; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Runtime.InteropServices; using System.Security.Cryptography; namespace AIProofread @@ -36,55 +39,25 @@ namespace AIProofread // 获取当前文档所有文本 string allText = doc.Range().Text; List list = new List(); + + //DocumentReader.ReadByVSTO(doc, Globals.ThisAddIn.Application, list); using (FileStream stream = new FileStream(docPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { - XWPFDocument ndoc = new XWPFDocument(stream); - var paragraphs = ndoc.Paragraphs; - int paragraphNumber = 1; - foreach (var bodyElement in ndoc.BodyElements) - { - // normal paragraph - if (bodyElement is XWPFParagraph p) - { - // 处理普通段落 - list.Add(new DocumentText(p.ParagraphText.Replace("\u0002", ""), paragraphNumber)); - paragraphNumber++; - } - // table -- vsto对于每个单元格的分段也会有 - else if (bodyElement is XWPFTable table) - { - foreach (var row in table.Rows) - { - foreach (var cell in row.GetTableCells()) - { - foreach (var pc in cell.Paragraphs) - { - list.Add(new DocumentText(pc.ParagraphText.Replace("\u0002", ""), paragraphNumber)); - paragraphNumber++; - } - } - //list.Add(string.Empty); - paragraphNumber++; - } - } - // 目录处理 - else if (bodyElement is XWPFSDT sdt) - { - string tocText = sdt.Content.Text; - - // 如果需要,可以进一步解析目录项// 例如,按换行符拆分目录内容 - var tocEntries = tocText.Split(new string[] { "\n", "\r", "\r\n", "\f" }, StringSplitOptions.None); - foreach (string entry in tocEntries) - { - - list.Add(new DocumentText(entry.Replace("\u0002", ""), paragraphNumber)); - paragraphNumber++; - } - } - } + ReadTextByNPOI(stream, list); + //try + //{ + + //} + //catch (POIXMLException npoiError) + //{ + // Logger.Log("GetAllText Error", npoiError); + // // Logger.Log("GetAllText", e); + // // return GetAllTextByVSTO(doc); + // // 读取文档 + // DocumentReader.ReadByVSTO(doc, Globals.ThisAddIn.Application, list); + //} } - Debug.WriteLine("GetAllText End ==>", DateTime.Now.ToLongTimeString()); var map = new Dictionary { { "list", list }, @@ -95,6 +68,55 @@ namespace AIProofread return map; } + private static void ReadTextByNPOI(FileStream stream, List list) + { + XWPFDocument ndoc = new XWPFDocument(stream); + var paragraphs = ndoc.Paragraphs; + int paragraphNumber = 1; + foreach (var bodyElement in ndoc.BodyElements) + { + // normal paragraph + if (bodyElement is XWPFParagraph p) + { + // 处理普通段落 + list.Add(new DocumentText(p.ParagraphText.Replace("\u0002", ""), paragraphNumber)); + paragraphNumber++; + } + // table -- vsto对于每个单元格的分段也会有 + else if (bodyElement is XWPFTable table) + { + foreach (var row in table.Rows) + { + foreach (var cell in row.GetTableCells()) + { + foreach (var pc in cell.Paragraphs) + { + list.Add(new DocumentText(pc.ParagraphText.Replace("\u0002", ""), paragraphNumber)); + paragraphNumber++; + } + } + //list.Add(string.Empty); + paragraphNumber++; + } + } + // 目录处理 + else if (bodyElement is XWPFSDT sdt) + { + string tocText = sdt.Content.Text; + + // 如果需要,可以进一步解析目录项// 例如,按换行符拆分目录内容 + var tocEntries = tocText.Split(new string[] { "\n", "\r", "\r\n", "\f" }, StringSplitOptions.None); + paragraphNumber+= tocEntries.Length; + // 暂时跳过目录 + //foreach (string entry in tocEntries) + //{ + // list.Add(new DocumentText(entry.Replace("\u0002", ""), paragraphNumber)); + // paragraphNumber++; + //} + } + } + } + public static string GetReadDocumentFilePath(Microsoft.Office.Interop.Word.Document doc) { // @@ -155,8 +177,7 @@ namespace AIProofread // 获取当前文档所有文本 string allText = doc.Range().Text; List list = new List(); - // // 开始分割 - MD5 md5 = new MD5CryptoServiceProvider(); + Paragraphs paragraphs = doc.Paragraphs; @@ -166,18 +187,22 @@ namespace AIProofread foreach (Paragraph p in paragraphs) { paragraphNumber++; - if (paragraphNumber % 20 == 0) - { - Debug.WriteLine("process paragraphNumber{0}", paragraphNumber); - } + //if (paragraphNumber % 20 == 0) + //{ + // Debug.WriteLine("process paragraphNumber{0}", paragraphNumber); + //} Range r = p.Range; string text = p.Range.Text; + if (text.Trim().Length == 0 || text.EndsWith("\r\a") || r.Tables.Count > 0) { continue; } list.Add(new DocumentText(text.Replace("\u0002", ""), paragraphNumber)); + Marshal.ReleaseComObject(p); } + Marshal.ReleaseComObject(paragraphs); + //for (; paragraphNumber <= total; paragraphNumber++) //{ diff --git a/updater/Form1.cs b/updater/Form1.cs index b6df72f..91b3cd1 100644 --- a/updater/Form1.cs +++ b/updater/Form1.cs @@ -19,6 +19,7 @@ namespace updater { private UpgradeInfo localVersion; private UpgradeInfo upgradeInfo; + private OfficeStarter appStarter = new OfficeStarter(); private static readonly string ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase; private static readonly string LocalVersionFilePath = ApplicationBase + Path.GetFileName("version.json"); public static readonly string CONFIG_FILE = AppDomain.CurrentDomain.BaseDirectory + "app.json"; @@ -30,7 +31,7 @@ namespace updater * gm-plugin.gachafun.com 正式发布 */ #if DEBUG - private static string UpgradeInfoURI = "http://gm-plugin.gachafun.com/"; + private static string UpgradeInfoURI = "https://gm-plugin.gachafun.com/"; #else private static string UpgradeInfoURI = "https://gm-plugin.gachafun.com/"; #endif @@ -125,17 +126,22 @@ namespace updater public string CheckHostAppRunning() { Process[] array = Process.GetProcesses(); + var hasWPS = false; + var hasWord = false; foreach (Process item2 in array) { - if (item2.ProcessName.Equals("wps")) + if (item2.ProcessName.Equals("WINWORD")) { - return "WPS"; + hasWord = true; } - else if (item2.ProcessName.Equals("WINWORD")) + else if (item2.ProcessName.Equals("wps")) { - return "Word"; + hasWPS = true; } } + if (hasWord && hasWPS) return "WPS与Word"; + if (hasWord) return "Word"; + if (hasWPS) return "WPS"; return null; } @@ -253,36 +259,63 @@ namespace updater progressBar1.Value = 100; // 获取升级包路径 string updateFileName = UpgradeDir + Path.GetFileName(upgradeInfo.DownloadUrl); - if (updateFileName.EndsWith(".exe")) + try { - StartInstallExe(updateFileName); - return; - } - - // 可以考虑备份旧文件 - //string destinationFolder = Path.Combine(applicationBase, "update\\old"); - //CopyDirectory(applicationBase, destinationFolder); - //ZipFile.ExtractToDirectory(zipFilePath, applicationBase); - - using (ZipArchive zip = ZipFile.OpenRead(updateFileName)) - { - foreach (ZipArchiveEntry entry in zip.Entries) + if (updateFileName.EndsWith(".exe")) { - // 采用覆盖模式进行解压 - try - { - entry.ExtractToFile(Path.Combine(ApplicationBase, entry.FullName), true); - } - catch (Exception) - { + StartInstallExe(updateFileName); + return; + } + // 可以考虑备份旧文件 + //string destinationFolder = Path.Combine(applicationBase, "update\\old"); + //CopyDirectory(applicationBase, destinationFolder); + //ZipFile.ExtractToDirectory(zipFilePath, applicationBase); + + using (ZipArchive zip = ZipFile.OpenRead(updateFileName)) + { + foreach (ZipArchiveEntry entry in zip.Entries) + { + // 采用覆盖模式进行解压 + try + { + entry.ExtractToFile(Path.Combine(ApplicationBase, entry.FullName), true); + } + catch (Exception) + { + + } } } + MessageBox.Show("更新完成, 您可以打开文档继续校对"); + // 保存最新版本日志 + try + { + File.WriteAllText(LocalVersionFilePath, updateSource); + } + catch (Exception) { } + appStarter.StartWPS(); + appStarter.StartMSOffice(); + this.Close(); + } + catch (Exception) + { + try + { + File.Delete(updateFileName); + }catch { } + var ret = MessageBox.Show("升级失败,是否需要手动执行更新?", "更新失败", MessageBoxButtons.YesNo); + if (ret == DialogResult.Yes) + { + Process.Start(upgradeInfo.DownloadUrl); + this.Close(); + } + else + { + ButtonProcess.Visible = true; + ButtonProcess.Text = "重新更新"; + } } - MessageBox.Show("更新完成, 您可以打开文档继续校对"); - // 保存最新版本日志 - File.WriteAllText(LocalVersionFilePath, updateSource); - this.Close(); } public static void CopyDirectory(string sourceFolder, string destinationFolder) { diff --git a/updater/OfficeStarter.cs b/updater/OfficeStarter.cs index 96f4bb8..0743311 100644 --- a/updater/OfficeStarter.cs +++ b/updater/OfficeStarter.cs @@ -7,51 +7,59 @@ namespace updater { public void StartWPS() { - if (UpdateData.GetInstance().ShouldRebootWPS) + try { - string text = RegistHelper.GetRegistData(Registry.CurrentUser, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Kingsoft Office", "DisplayIcon"); - if (string.IsNullOrWhiteSpace(text)) + if (UpdateData.GetInstance().ShouldRebootWPS) { - text = RegistHelper.GetAllRegistData(RegistryHive.LocalMachine, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Kingsoft Office", "DisplayIcon"); - } - if (!string.IsNullOrWhiteSpace(text)) - { - text = text.Substring(0, text.LastIndexOf("WPS Office")) + "WPS Office\\ksolaunch.exe"; - Process.Start(text); + string text = RegistHelper.GetRegistData(Registry.CurrentUser, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Kingsoft Office", "DisplayIcon"); + if (string.IsNullOrWhiteSpace(text)) + { + text = RegistHelper.GetAllRegistData(RegistryHive.LocalMachine, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Kingsoft Office", "DisplayIcon"); + } + if (!string.IsNullOrWhiteSpace(text)) + { + text = text.Substring(0, text.LastIndexOf("WPS Office")) + "WPS Office\\ksolaunch.exe"; + Process.Start(text); + } } } + catch { } } public void StartMSOffice() { - if (UpdateData.GetInstance().ShouldRebootMSOffice) + try { - string allRegistData = RegistHelper.GetAllRegistData(RegistryHive.LocalMachine, "SOFTWARE\\Microsoft\\Office\\16.0\\Word\\InstallRoot", "Path"); - //检查2016 / 2019 / 365版本路径 - if (string.IsNullOrWhiteSpace(allRegistData)) + if (UpdateData.GetInstance().ShouldRebootMSOffice) { - allRegistData = RegistHelper.GetAllRegistData(RegistryHive.LocalMachine, "SOFTWARE\\Microsoft\\Office\\15.0\\Common\\InstallRoot", "Path"); - // 检查2013版本路径 + string allRegistData = RegistHelper.GetAllRegistData(RegistryHive.LocalMachine, "SOFTWARE\\Microsoft\\Office\\16.0\\Word\\InstallRoot", "Path"); + //检查2016 / 2019 / 365版本路径 + if (string.IsNullOrWhiteSpace(allRegistData)) + { + allRegistData = RegistHelper.GetAllRegistData(RegistryHive.LocalMachine, "SOFTWARE\\Microsoft\\Office\\15.0\\Common\\InstallRoot", "Path"); + // 检查2013版本路径 + } + if (string.IsNullOrWhiteSpace(allRegistData)) + { + allRegistData = RegistHelper.GetAllRegistData(RegistryHive.LocalMachine, "SOFTWARE\\Microsoft\\Office\\14.0\\Common\\InstallRoot", "Path"); + // 检查2010版本路径 + } + if (string.IsNullOrWhiteSpace(allRegistData)) + { + allRegistData = RegistHelper.GetAllRegistData(RegistryHive.LocalMachine, "SOFTWARE\\Microsoft\\Office\\12.0\\Common\\InstallRoot", "Path"); + //检查2007版本路径 + } + if (!string.IsNullOrWhiteSpace(allRegistData)) + { + allRegistData += "WINWORD.exe"; + //MSOffice启动路径 + Process.Start(allRegistData); + } + // 未能从注册表找到MS Office 安装路径 + // 没有找到 直接不处理了 } - if (string.IsNullOrWhiteSpace(allRegistData)) - { - allRegistData = RegistHelper.GetAllRegistData(RegistryHive.LocalMachine, "SOFTWARE\\Microsoft\\Office\\14.0\\Common\\InstallRoot", "Path"); - // 检查2010版本路径 - } - if (string.IsNullOrWhiteSpace(allRegistData)) - { - allRegistData = RegistHelper.GetAllRegistData(RegistryHive.LocalMachine, "SOFTWARE\\Microsoft\\Office\\12.0\\Common\\InstallRoot", "Path"); - //检查2007版本路径 - } - if (!string.IsNullOrWhiteSpace(allRegistData)) - { - allRegistData += "WINWORD.exe"; - //MSOffice启动路径 - Process.Start(allRegistData); - } - // 未能从注册表找到MS Office 安装路径 - // 没有找到 直接不处理了 } + catch{} } } } diff --git a/util-lib/CorrectItem.cs b/util-lib/CorrectItem.cs index 80de143..231ae9f 100644 --- a/util-lib/CorrectItem.cs +++ b/util-lib/CorrectItem.cs @@ -39,7 +39,7 @@ namespace UtilLib /// /// 校对状态 /// - [JsonProperty("is_accept")] + [JsonProperty("isAccept")] public int IsAccept { get; set; } /// /// 校对项颜色