chr
2024-11-02 b5234c5ab1e9e6826b8d8fc1e95fa752aaa40b74
优化程序
15个文件已添加
28个文件已修改
3115 ■■■■ 已修改文件
.vs/SwPlugin/v17/DocumentLayout.backup.json 252 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.vs/SwPlugin/v17/DocumentLayout.json 204 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
AutoUpdater/MainWindow.xaml.cs 83 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
InnoSetupScript/PdmSwPlugin.iss 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Md5Reader/App.config 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Md5Reader/App.xaml 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Md5Reader/App.xaml.cs 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Md5Reader/MainWindow.xaml 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Md5Reader/MainWindow.xaml.cs 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Md5Reader/Md5Reader.csproj 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Md5Reader/Properties/AssemblyInfo.cs 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Md5Reader/Properties/Resources.Designer.cs 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Md5Reader/Properties/Resources.resx 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Md5Reader/Properties/Settings.Designer.cs 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Md5Reader/Properties/Settings.settings 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PdmSw/SwAddin.cs 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PdmSwPlugin.Common/BomIniter/NameUtil.cs 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PdmSwPlugin.Common/BomIniter/YwtBomIniter.cs 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PdmSwPlugin.Common/Control/RichHisWindow.xaml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
PdmSwPlugin.Common/Control/RichHisWindow.xaml.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PdmSwPlugin.Common/Entity/Pdm/PdmBom.cs 36 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PdmSwPlugin.Common/Setting/CustomerSetting.cs 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PdmSwPlugin.Common/Util/CustomPropertyUtil.cs 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PdmSwPlugin.Common/Util/LimitedConcurrencyLevelTaskScheduler.cs 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PdmSwPlugin.Common/Util/Pdm/BomTreeReader.cs 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PdmSwPlugin.DrawApprove/DrawApprove.xaml.cs 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PdmSwPlugin.Main/Constant/PluginConst.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
PdmSwPlugin.Main/MainControl.xaml.cs 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PdmSwPlugin.Main/MainTab.xaml 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PdmSwPlugin.Main/MainTab.xaml.cs 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PdmSwPlugin.Main/SwAddIn/MainControl.cs 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PdmSwPlugin.PDM/PdmControl.xaml.cs 364 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PdmSwPlugin.PDM/PdmSwPlugin.PDM.csproj 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PdmSwPlugin.PDM/packages.config 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PdmSwPlugin.PropertySetting/CommonSettingControl.xaml.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PdmSwPlugin.PropertySetting/Panel/Model/JgjBasePanelModel.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PdmSwPlugin.PropertySetting/PdmSwPlugin.PropertySetting.csproj 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PdmSwPlugin.PropertySetting/SettingControl.xaml 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PdmSwPlugin.PropertySetting/SettingControl.xaml.cs 715 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PdmSwPlugin.PropertySetting/Tab/JgjPartTab.xaml 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PdmSwPlugin.PropertySetting/Tab/JgjPartTab.xaml.cs 473 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SolidWorksListener/Listener.cs 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WpfUI/AsyncAttacher.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
.vs/SwPlugin/v17/DocumentLayout.backup.json
@@ -3,36 +3,48 @@
  "WorkspaceRootPath": "D:\\Workspace\\PdmSwPlugin2\\",
  "Documents": [
    {
      "AbsoluteMoniker": "D:0:0:{BE239D32-7253-4D19-8793-159E98545B55}|PdmSwPlugin.DrawApprove\\PdmSwPlugin.DrawApprove.csproj|d:\\workspace\\pdmswplugin2\\pdmswplugin.drawapprove\\drawapprove.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{BE239D32-7253-4D19-8793-159E98545B55}|PdmSwPlugin.DrawApprove\\PdmSwPlugin.DrawApprove.csproj|solutionrelative:pdmswplugin.drawapprove\\drawapprove.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
      "AbsoluteMoniker": "D:0:0:{6E609A8C-583B-4607-A510-FA84218C4A31}|PdmSwPlugin.Main\\PdmSwPlugin.Main.csproj|d:\\workspace\\pdmswplugin2\\pdmswplugin.main\\constant\\pluginconst.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{6E609A8C-583B-4607-A510-FA84218C4A31}|PdmSwPlugin.Main\\PdmSwPlugin.Main.csproj|solutionrelative:pdmswplugin.main\\constant\\pluginconst.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{1033FBD8-8700-4CD0-808A-BB97DB057A6B}|PdmSwPlugin.PDM\\PdmSwPlugin.PDM.csproj|d:\\workspace\\pdmswplugin2\\pdmswplugin.pdm\\pdmcontrol.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}",
      "RelativeMoniker": "D:0:0:{1033FBD8-8700-4CD0-808A-BB97DB057A6B}|PdmSwPlugin.PDM\\PdmSwPlugin.PDM.csproj|solutionrelative:pdmswplugin.pdm\\pdmcontrol.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{BE239D32-7253-4D19-8793-159E98545B55}|PdmSwPlugin.DrawApprove\\PdmSwPlugin.DrawApprove.csproj|d:\\workspace\\pdmswplugin2\\pdmswplugin.drawapprove\\drawapprove.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}",
      "RelativeMoniker": "D:0:0:{BE239D32-7253-4D19-8793-159E98545B55}|PdmSwPlugin.DrawApprove\\PdmSwPlugin.DrawApprove.csproj|solutionrelative:pdmswplugin.drawapprove\\drawapprove.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{1033FBD8-8700-4CD0-808A-BB97DB057A6B}|PdmSwPlugin.PDM\\PdmSwPlugin.PDM.csproj|d:\\workspace\\pdmswplugin2\\pdmswplugin.pdm\\pdmcontrol.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "AbsoluteMoniker": "D:0:0:{1033FBD8-8700-4CD0-808A-BB97DB057A6B}|PdmSwPlugin.PDM\\PdmSwPlugin.PDM.csproj|D:\\Workspace\\PdmSwPlugin2\\pdmswplugin.pdm\\pdmcontrol.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{1033FBD8-8700-4CD0-808A-BB97DB057A6B}|PdmSwPlugin.PDM\\PdmSwPlugin.PDM.csproj|solutionrelative:pdmswplugin.pdm\\pdmcontrol.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{7ACEDAA9-2DE8-4485-837A-E7D58812A6DC}|PdmSw\\PdmSw.csproj|d:\\workspace\\pdmswplugin2\\pdmsw\\swaddin.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "AbsoluteMoniker": "D:0:0:{E17EF6B6-EE83-45AA-B0C0-E3A097089E97}|PdmSwPlugin.Common\\PdmSwPlugin.Common.csproj|D:\\Workspace\\PdmSwPlugin2\\pdmswplugin.common\\entity\\pdm\\pdmbom.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{E17EF6B6-EE83-45AA-B0C0-E3A097089E97}|PdmSwPlugin.Common\\PdmSwPlugin.Common.csproj|solutionrelative:pdmswplugin.common\\entity\\pdm\\pdmbom.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{1033FBD8-8700-4CD0-808A-BB97DB057A6B}|PdmSwPlugin.PDM\\PdmSwPlugin.PDM.csproj|D:\\Workspace\\PdmSwPlugin2\\pdmswplugin.pdm\\pdmcontrol.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}",
      "RelativeMoniker": "D:0:0:{1033FBD8-8700-4CD0-808A-BB97DB057A6B}|PdmSwPlugin.PDM\\PdmSwPlugin.PDM.csproj|solutionrelative:pdmswplugin.pdm\\pdmcontrol.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{E17EF6B6-EE83-45AA-B0C0-E3A097089E97}|PdmSwPlugin.Common\\PdmSwPlugin.Common.csproj|D:\\Workspace\\PdmSwPlugin2\\pdmswplugin.common\\util\\pdm\\bomtreereader.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{E17EF6B6-EE83-45AA-B0C0-E3A097089E97}|PdmSwPlugin.Common\\PdmSwPlugin.Common.csproj|solutionrelative:pdmswplugin.common\\util\\pdm\\bomtreereader.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{E17EF6B6-EE83-45AA-B0C0-E3A097089E97}|PdmSwPlugin.Common\\PdmSwPlugin.Common.csproj|D:\\Workspace\\PdmSwPlugin2\\pdmswplugin.common\\bominiter\\ywtbominiter.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{E17EF6B6-EE83-45AA-B0C0-E3A097089E97}|PdmSwPlugin.Common\\PdmSwPlugin.Common.csproj|solutionrelative:pdmswplugin.common\\bominiter\\ywtbominiter.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{3AEC586C-B22A-4ADB-B4AB-10AA660F79EC}|Md5Reader\\Md5Reader.csproj|D:\\Workspace\\PdmSwPlugin2\\md5reader\\mainwindow.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{3AEC586C-B22A-4ADB-B4AB-10AA660F79EC}|Md5Reader\\Md5Reader.csproj|solutionrelative:md5reader\\mainwindow.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{6E609A8C-583B-4607-A510-FA84218C4A31}|PdmSwPlugin.Main\\PdmSwPlugin.Main.csproj|D:\\Workspace\\PdmSwPlugin2\\pdmswplugin.main\\maincontrol.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{6E609A8C-583B-4607-A510-FA84218C4A31}|PdmSwPlugin.Main\\PdmSwPlugin.Main.csproj|solutionrelative:pdmswplugin.main\\maincontrol.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{CB3551F6-0C4A-4537-9A04-1E40CD475479}|SolidWorksListener\\SolidWorksListener.csproj|D:\\Workspace\\PdmSwPlugin2\\solidworkslistener\\listener.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{CB3551F6-0C4A-4537-9A04-1E40CD475479}|SolidWorksListener\\SolidWorksListener.csproj|solutionrelative:solidworkslistener\\listener.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{4536570F-AD3C-4D24-870A-63C9E9CE0FED}|WpfUI\\WpfUI.csproj|D:\\Workspace\\PdmSwPlugin2\\wpfui\\asyncattacher.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{4536570F-AD3C-4D24-870A-63C9E9CE0FED}|WpfUI\\WpfUI.csproj|solutionrelative:wpfui\\asyncattacher.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{7ACEDAA9-2DE8-4485-837A-E7D58812A6DC}|PdmSw\\PdmSw.csproj|D:\\Workspace\\PdmSwPlugin2\\pdmsw\\swaddin.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{7ACEDAA9-2DE8-4485-837A-E7D58812A6DC}|PdmSw\\PdmSw.csproj|solutionrelative:pdmsw\\swaddin.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{6E609A8C-583B-4607-A510-FA84218C4A31}|PdmSwPlugin.Main\\PdmSwPlugin.Main.csproj|d:\\workspace\\pdmswplugin2\\pdmswplugin.main\\swaddin\\maincontrol.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{6E609A8C-583B-4607-A510-FA84218C4A31}|PdmSwPlugin.Main\\PdmSwPlugin.Main.csproj|solutionrelative:pdmswplugin.main\\swaddin\\maincontrol.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{6E609A8C-583B-4607-A510-FA84218C4A31}|PdmSwPlugin.Main\\PdmSwPlugin.Main.csproj|d:\\workspace\\pdmswplugin2\\pdmswplugin.main\\eventhandler\\baseattacher.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{6E609A8C-583B-4607-A510-FA84218C4A31}|PdmSwPlugin.Main\\PdmSwPlugin.Main.csproj|solutionrelative:pdmswplugin.main\\eventhandler\\baseattacher.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{7ACEDAA9-2DE8-4485-837A-E7D58812A6DC}|PdmSw\\PdmSw.csproj|d:\\workspace\\pdmswplugin2\\pdmsw\\log4net.config||{FA3CD31E-987B-443A-9B81-186104E8DAC1}",
      "RelativeMoniker": "D:0:0:{7ACEDAA9-2DE8-4485-837A-E7D58812A6DC}|PdmSw\\PdmSw.csproj|solutionrelative:pdmsw\\log4net.config||{FA3CD31E-987B-443A-9B81-186104E8DAC1}"
    }
  ],
  "DocumentGroupContainers": [
@@ -42,109 +54,139 @@
      "DocumentGroups": [
        {
          "DockedWidth": 200,
          "SelectedChildIndex": 2,
          "SelectedChildIndex": 4,
          "Children": [
            {
              "$type": "Document",
              "DocumentIndex": 2,
              "Title": "DrawApprove.xaml",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.DrawApprove\\DrawApprove.xaml",
              "RelativeDocumentMoniker": "PdmSwPlugin.DrawApprove\\DrawApprove.xaml",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.DrawApprove\\DrawApprove.xaml",
              "RelativeToolTip": "PdmSwPlugin.DrawApprove\\DrawApprove.xaml",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003549|",
              "WhenOpened": "2024-10-09T03:31:27.843Z",
              "EditorCaption": ""
              "DocumentIndex": 5,
              "Title": "YwtBomIniter.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Common\\BomIniter\\YwtBomIniter.cs",
              "RelativeDocumentMoniker": "PdmSwPlugin.Common\\BomIniter\\YwtBomIniter.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Common\\BomIniter\\YwtBomIniter.cs",
              "RelativeToolTip": "PdmSwPlugin.Common\\BomIniter\\YwtBomIniter.cs",
              "ViewState": "AgIAAEEAAAAAAAAAAAAUwBIAAAAXAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-10-31T09:13:45.395Z"
            },
            {
              "$type": "Document",
              "DocumentIndex": 1,
              "DocumentIndex": 3,
              "Title": "PdmControl.xaml",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.PDM\\PdmControl.xaml",
              "RelativeDocumentMoniker": "PdmSwPlugin.PDM\\PdmControl.xaml",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.PDM\\PdmControl.xaml",
              "RelativeToolTip": "PdmSwPlugin.PDM\\PdmControl.xaml",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003549|",
              "WhenOpened": "2024-10-09T03:30:57.686Z",
              "EditorCaption": ""
              "WhenOpened": "2024-10-31T09:12:36.773Z"
            },
            {
              "$type": "Document",
              "DocumentIndex": 0,
              "Title": "DrawApprove.xaml.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.DrawApprove\\DrawApprove.xaml.cs",
              "RelativeDocumentMoniker": "PdmSwPlugin.DrawApprove\\DrawApprove.xaml.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.DrawApprove\\DrawApprove.xaml.cs",
              "RelativeToolTip": "PdmSwPlugin.DrawApprove\\DrawApprove.xaml.cs",
              "ViewState": "AgIAAAYCAAAAAAAAAAAkwCICAAAAAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-10-09T03:22:18.864Z",
              "EditorCaption": ""
            },
            {
              "$type": "Document",
              "DocumentIndex": 7,
              "Title": "log4net.config",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\PdmSw\\log4net.config",
              "RelativeDocumentMoniker": "PdmSw\\log4net.config",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\PdmSw\\log4net.config",
              "RelativeToolTip": "PdmSw\\log4net.config",
              "ViewState": "AgIAAAAAAAAAAAAAAAAAAA0AAAAQAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000601|",
              "WhenOpened": "2024-09-26T10:24:04.161Z",
              "EditorCaption": ""
            },
            {
              "$type": "Document",
              "DocumentIndex": 4,
              "Title": "SwAddin.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\PdmSw\\SwAddin.cs",
              "RelativeDocumentMoniker": "PdmSw\\SwAddin.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\PdmSw\\SwAddin.cs",
              "RelativeToolTip": "PdmSw\\SwAddin.cs",
              "ViewState": "AgIAACIAAAAAAAAAAAA5wCkAAAAvAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-09-26T08:51:00.927Z",
              "EditorCaption": ""
            },
            {
              "$type": "Document",
              "DocumentIndex": 6,
              "Title": "BaseAttacher.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Main\\EventHandler\\BaseAttacher.cs",
              "RelativeDocumentMoniker": "PdmSwPlugin.Main\\EventHandler\\BaseAttacher.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Main\\EventHandler\\BaseAttacher.cs",
              "RelativeToolTip": "PdmSwPlugin.Main\\EventHandler\\BaseAttacher.cs",
              "ViewState": "AgIAAKoAAAAAAAAAAAA0wMcAAAApAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-09-25T09:56:45.504Z",
              "EditorCaption": ""
            },
            {
              "$type": "Document",
              "DocumentIndex": 5,
              "Title": "MainControl.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Main\\SwAddIn\\MainControl.cs",
              "RelativeDocumentMoniker": "PdmSwPlugin.Main\\SwAddIn\\MainControl.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Main\\SwAddIn\\MainControl.cs",
              "RelativeToolTip": "PdmSwPlugin.Main\\SwAddIn\\MainControl.cs",
              "ViewState": "AgIAAIwAAAAAAAAAAAA+wOQAAABDAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-09-25T09:54:37.505Z",
              "EditorCaption": ""
            },
            {
              "$type": "Document",
              "DocumentIndex": 3,
              "DocumentIndex": 1,
              "Title": "PdmControl.xaml.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.PDM\\PdmControl.xaml.cs",
              "RelativeDocumentMoniker": "PdmSwPlugin.PDM\\PdmControl.xaml.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.PDM\\PdmControl.xaml.cs",
              "RelativeToolTip": "PdmSwPlugin.PDM\\PdmControl.xaml.cs",
              "ViewState": "AgIAAM0EAAAAAAAAAAAAAOEEAAAvAAAAAAAAAA==",
              "ViewState": "AgIAALUEAAAAAAAAAAAuwMUEAABAAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-09-25T06:09:00.747Z",
              "WhenOpened": "2024-10-31T08:50:14.505Z"
            },
            {
              "$type": "Document",
              "DocumentIndex": 4,
              "Title": "BomTreeReader.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Common\\Util\\Pdm\\BomTreeReader.cs",
              "RelativeDocumentMoniker": "PdmSwPlugin.Common\\Util\\Pdm\\BomTreeReader.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Common\\Util\\Pdm\\BomTreeReader.cs",
              "RelativeToolTip": "PdmSwPlugin.Common\\Util\\Pdm\\BomTreeReader.cs",
              "ViewState": "AgIAAPsAAAAAAAAAAAAUwBABAAAgAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-10-31T08:33:38.547Z"
            },
            {
              "$type": "Document",
              "DocumentIndex": 0,
              "Title": "PluginConst.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Main\\Constant\\PluginConst.cs",
              "RelativeDocumentMoniker": "PdmSwPlugin.Main\\Constant\\PluginConst.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Main\\Constant\\PluginConst.cs",
              "RelativeToolTip": "PdmSwPlugin.Main\\Constant\\PluginConst.cs",
              "ViewState": "AgIAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-10-14T04:01:41.756Z",
              "EditorCaption": ""
            },
            {
              "$type": "Document",
              "DocumentIndex": 2,
              "Title": "PdmBom.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Common\\Entity\\Pdm\\PdmBom.cs",
              "RelativeDocumentMoniker": "PdmSwPlugin.Common\\Entity\\Pdm\\PdmBom.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Common\\Entity\\Pdm\\PdmBom.cs",
              "RelativeToolTip": "PdmSwPlugin.Common\\Entity\\Pdm\\PdmBom.cs",
              "ViewState": "AgIAAIgAAAAAAAAAAAA+wJYAAAAdAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-10-31T08:32:38.632Z"
            },
            {
              "$type": "Document",
              "DocumentIndex": 6,
              "Title": "MainWindow.xaml.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\Md5Reader\\MainWindow.xaml.cs",
              "RelativeDocumentMoniker": "Md5Reader\\MainWindow.xaml.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\Md5Reader\\MainWindow.xaml.cs",
              "RelativeToolTip": "Md5Reader\\MainWindow.xaml.cs",
              "ViewState": "AgIAAAAAAAAAAAAAAAAAABAAAABDAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-10-30T02:39:22.183Z"
            },
            {
              "$type": "Document",
              "DocumentIndex": 7,
              "Title": "MainControl.xaml.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Main\\MainControl.xaml.cs",
              "RelativeDocumentMoniker": "PdmSwPlugin.Main\\MainControl.xaml.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Main\\MainControl.xaml.cs",
              "RelativeToolTip": "PdmSwPlugin.Main\\MainControl.xaml.cs",
              "ViewState": "AgIAAMAAAAAAAAAAAAAYwMoAAAAAAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-10-14T04:24:56.766Z"
            },
            {
              "$type": "Document",
              "DocumentIndex": 8,
              "Title": "Listener.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\SolidWorksListener\\Listener.cs",
              "RelativeDocumentMoniker": "SolidWorksListener\\Listener.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\SolidWorksListener\\Listener.cs",
              "RelativeToolTip": "SolidWorksListener\\Listener.cs",
              "ViewState": "AgIAANAAAAAAAAAAAADwv90AAAAiAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-10-14T03:42:50.289Z"
            },
            {
              "$type": "Document",
              "DocumentIndex": 9,
              "Title": "AsyncAttacher.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\WpfUI\\AsyncAttacher.cs",
              "RelativeDocumentMoniker": "WpfUI\\AsyncAttacher.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\WpfUI\\AsyncAttacher.cs",
              "RelativeToolTip": "WpfUI\\AsyncAttacher.cs",
              "ViewState": "AgIAAAAAAAAAAAAAAAAAAA8AAAAJAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-10-14T03:36:12.415Z"
            },
            {
              "$type": "Document",
              "DocumentIndex": 10,
              "Title": "SwAddin.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\PdmSw\\SwAddin.cs",
              "RelativeDocumentMoniker": "PdmSw\\SwAddin.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\PdmSw\\SwAddin.cs",
              "RelativeToolTip": "PdmSw\\SwAddin.cs",
              "ViewState": "AgIAABMBAAAAAAAAAAAkwCYBAAAkAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-10-14T01:09:55.509Z"
            }
          ]
        }
.vs/SwPlugin/v17/DocumentLayout.json
@@ -3,24 +3,48 @@
  "WorkspaceRootPath": "D:\\Workspace\\PdmSwPlugin2\\",
  "Documents": [
    {
      "AbsoluteMoniker": "D:0:0:{1033FBD8-8700-4CD0-808A-BB97DB057A6B}|PdmSwPlugin.PDM\\PdmSwPlugin.PDM.csproj|d:\\workspace\\pdmswplugin2\\pdmswplugin.pdm\\pdmcontrol.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "AbsoluteMoniker": "D:0:0:{6E609A8C-583B-4607-A510-FA84218C4A31}|PdmSwPlugin.Main\\PdmSwPlugin.Main.csproj|d:\\workspace\\pdmswplugin2\\pdmswplugin.main\\constant\\pluginconst.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{6E609A8C-583B-4607-A510-FA84218C4A31}|PdmSwPlugin.Main\\PdmSwPlugin.Main.csproj|solutionrelative:pdmswplugin.main\\constant\\pluginconst.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{1033FBD8-8700-4CD0-808A-BB97DB057A6B}|PdmSwPlugin.PDM\\PdmSwPlugin.PDM.csproj|D:\\Workspace\\PdmSwPlugin2\\pdmswplugin.pdm\\pdmcontrol.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{1033FBD8-8700-4CD0-808A-BB97DB057A6B}|PdmSwPlugin.PDM\\PdmSwPlugin.PDM.csproj|solutionrelative:pdmswplugin.pdm\\pdmcontrol.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{1033FBD8-8700-4CD0-808A-BB97DB057A6B}|PdmSwPlugin.PDM\\PdmSwPlugin.PDM.csproj|d:\\workspace\\pdmswplugin2\\pdmswplugin.pdm\\pdmcontrol.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}",
      "AbsoluteMoniker": "D:0:0:{E17EF6B6-EE83-45AA-B0C0-E3A097089E97}|PdmSwPlugin.Common\\PdmSwPlugin.Common.csproj|D:\\Workspace\\PdmSwPlugin2\\pdmswplugin.common\\entity\\pdm\\pdmbom.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{E17EF6B6-EE83-45AA-B0C0-E3A097089E97}|PdmSwPlugin.Common\\PdmSwPlugin.Common.csproj|solutionrelative:pdmswplugin.common\\entity\\pdm\\pdmbom.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{1033FBD8-8700-4CD0-808A-BB97DB057A6B}|PdmSwPlugin.PDM\\PdmSwPlugin.PDM.csproj|D:\\Workspace\\PdmSwPlugin2\\pdmswplugin.pdm\\pdmcontrol.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}",
      "RelativeMoniker": "D:0:0:{1033FBD8-8700-4CD0-808A-BB97DB057A6B}|PdmSwPlugin.PDM\\PdmSwPlugin.PDM.csproj|solutionrelative:pdmswplugin.pdm\\pdmcontrol.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{7ACEDAA9-2DE8-4485-837A-E7D58812A6DC}|PdmSw\\PdmSw.csproj|d:\\workspace\\pdmswplugin2\\pdmsw\\swaddin.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "AbsoluteMoniker": "D:0:0:{E17EF6B6-EE83-45AA-B0C0-E3A097089E97}|PdmSwPlugin.Common\\PdmSwPlugin.Common.csproj|D:\\Workspace\\PdmSwPlugin2\\pdmswplugin.common\\util\\pdm\\bomtreereader.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{E17EF6B6-EE83-45AA-B0C0-E3A097089E97}|PdmSwPlugin.Common\\PdmSwPlugin.Common.csproj|solutionrelative:pdmswplugin.common\\util\\pdm\\bomtreereader.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{E17EF6B6-EE83-45AA-B0C0-E3A097089E97}|PdmSwPlugin.Common\\PdmSwPlugin.Common.csproj|D:\\Workspace\\PdmSwPlugin2\\pdmswplugin.common\\bominiter\\ywtbominiter.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{E17EF6B6-EE83-45AA-B0C0-E3A097089E97}|PdmSwPlugin.Common\\PdmSwPlugin.Common.csproj|solutionrelative:pdmswplugin.common\\bominiter\\ywtbominiter.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{3AEC586C-B22A-4ADB-B4AB-10AA660F79EC}|Md5Reader\\Md5Reader.csproj|D:\\Workspace\\PdmSwPlugin2\\md5reader\\mainwindow.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{3AEC586C-B22A-4ADB-B4AB-10AA660F79EC}|Md5Reader\\Md5Reader.csproj|solutionrelative:md5reader\\mainwindow.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{6E609A8C-583B-4607-A510-FA84218C4A31}|PdmSwPlugin.Main\\PdmSwPlugin.Main.csproj|D:\\Workspace\\PdmSwPlugin2\\pdmswplugin.main\\maincontrol.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{6E609A8C-583B-4607-A510-FA84218C4A31}|PdmSwPlugin.Main\\PdmSwPlugin.Main.csproj|solutionrelative:pdmswplugin.main\\maincontrol.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{CB3551F6-0C4A-4537-9A04-1E40CD475479}|SolidWorksListener\\SolidWorksListener.csproj|D:\\Workspace\\PdmSwPlugin2\\solidworkslistener\\listener.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{CB3551F6-0C4A-4537-9A04-1E40CD475479}|SolidWorksListener\\SolidWorksListener.csproj|solutionrelative:solidworkslistener\\listener.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{4536570F-AD3C-4D24-870A-63C9E9CE0FED}|WpfUI\\WpfUI.csproj|D:\\Workspace\\PdmSwPlugin2\\wpfui\\asyncattacher.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{4536570F-AD3C-4D24-870A-63C9E9CE0FED}|WpfUI\\WpfUI.csproj|solutionrelative:wpfui\\asyncattacher.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{7ACEDAA9-2DE8-4485-837A-E7D58812A6DC}|PdmSw\\PdmSw.csproj|D:\\Workspace\\PdmSwPlugin2\\pdmsw\\swaddin.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{7ACEDAA9-2DE8-4485-837A-E7D58812A6DC}|PdmSw\\PdmSw.csproj|solutionrelative:pdmsw\\swaddin.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{6E609A8C-583B-4607-A510-FA84218C4A31}|PdmSwPlugin.Main\\PdmSwPlugin.Main.csproj|d:\\workspace\\pdmswplugin2\\pdmswplugin.main\\swaddin\\maincontrol.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{6E609A8C-583B-4607-A510-FA84218C4A31}|PdmSwPlugin.Main\\PdmSwPlugin.Main.csproj|solutionrelative:pdmswplugin.main\\swaddin\\maincontrol.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{6E609A8C-583B-4607-A510-FA84218C4A31}|PdmSwPlugin.Main\\PdmSwPlugin.Main.csproj|d:\\workspace\\pdmswplugin2\\pdmswplugin.main\\eventhandler\\baseattacher.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{6E609A8C-583B-4607-A510-FA84218C4A31}|PdmSwPlugin.Main\\PdmSwPlugin.Main.csproj|solutionrelative:pdmswplugin.main\\eventhandler\\baseattacher.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    }
  ],
  "DocumentGroupContainers": [
@@ -34,67 +58,135 @@
          "Children": [
            {
              "$type": "Document",
              "DocumentIndex": 1,
              "DocumentIndex": 5,
              "Title": "YwtBomIniter.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Common\\BomIniter\\YwtBomIniter.cs",
              "RelativeDocumentMoniker": "PdmSwPlugin.Common\\BomIniter\\YwtBomIniter.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Common\\BomIniter\\YwtBomIniter.cs",
              "RelativeToolTip": "PdmSwPlugin.Common\\BomIniter\\YwtBomIniter.cs",
              "ViewState": "AgIAAEEAAAAAAAAAAAAUwBIAAAAXAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-10-31T09:13:45.395Z"
            },
            {
              "$type": "Document",
              "DocumentIndex": 3,
              "Title": "PdmControl.xaml",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.PDM\\PdmControl.xaml",
              "RelativeDocumentMoniker": "PdmSwPlugin.PDM\\PdmControl.xaml",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.PDM\\PdmControl.xaml",
              "RelativeToolTip": "PdmSwPlugin.PDM\\PdmControl.xaml",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003549|",
              "WhenOpened": "2024-10-09T03:30:57.686Z",
              "EditorCaption": ""
              "WhenOpened": "2024-10-31T09:12:36.773Z"
            },
            {
              "$type": "Document",
              "DocumentIndex": 2,
              "Title": "SwAddin.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\PdmSw\\SwAddin.cs",
              "RelativeDocumentMoniker": "PdmSw\\SwAddin.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\PdmSw\\SwAddin.cs",
              "RelativeToolTip": "PdmSw\\SwAddin.cs",
              "ViewState": "AgIAACIAAAAAAAAAAAA5wCkAAAAvAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-09-26T08:51:00.927Z",
              "EditorCaption": ""
            },
            {
              "$type": "Document",
              "DocumentIndex": 4,
              "Title": "BaseAttacher.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Main\\EventHandler\\BaseAttacher.cs",
              "RelativeDocumentMoniker": "PdmSwPlugin.Main\\EventHandler\\BaseAttacher.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Main\\EventHandler\\BaseAttacher.cs",
              "RelativeToolTip": "PdmSwPlugin.Main\\EventHandler\\BaseAttacher.cs",
              "ViewState": "AgIAAKoAAAAAAAAAAAA0wMcAAAApAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-09-25T09:56:45.504Z",
              "EditorCaption": ""
            },
            {
              "$type": "Document",
              "DocumentIndex": 3,
              "Title": "MainControl.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Main\\SwAddIn\\MainControl.cs",
              "RelativeDocumentMoniker": "PdmSwPlugin.Main\\SwAddIn\\MainControl.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Main\\SwAddIn\\MainControl.cs",
              "RelativeToolTip": "PdmSwPlugin.Main\\SwAddIn\\MainControl.cs",
              "ViewState": "AgIAAIwAAAAAAAAAAAA+wOQAAABDAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-09-25T09:54:37.505Z",
              "EditorCaption": ""
            },
            {
              "$type": "Document",
              "DocumentIndex": 0,
              "DocumentIndex": 1,
              "Title": "PdmControl.xaml.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.PDM\\PdmControl.xaml.cs",
              "RelativeDocumentMoniker": "PdmSwPlugin.PDM\\PdmControl.xaml.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.PDM\\PdmControl.xaml.cs",
              "RelativeToolTip": "PdmSwPlugin.PDM\\PdmControl.xaml.cs",
              "ViewState": "AgIAANAEAAAAAAAAAAAAAOIEAAAZAAAAAAAAAA==",
              "ViewState": "AgIAALUEAAAAAAAAAAAuwMUEAABAAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-09-25T06:09:00.747Z",
              "WhenOpened": "2024-10-31T08:50:14.505Z"
            },
            {
              "$type": "Document",
              "DocumentIndex": 4,
              "Title": "BomTreeReader.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Common\\Util\\Pdm\\BomTreeReader.cs",
              "RelativeDocumentMoniker": "PdmSwPlugin.Common\\Util\\Pdm\\BomTreeReader.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Common\\Util\\Pdm\\BomTreeReader.cs",
              "RelativeToolTip": "PdmSwPlugin.Common\\Util\\Pdm\\BomTreeReader.cs",
              "ViewState": "AgIAAPsAAAAAAAAAAAAUwBABAAAgAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-10-31T08:33:38.547Z"
            },
            {
              "$type": "Document",
              "DocumentIndex": 0,
              "Title": "PluginConst.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Main\\Constant\\PluginConst.cs",
              "RelativeDocumentMoniker": "PdmSwPlugin.Main\\Constant\\PluginConst.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Main\\Constant\\PluginConst.cs",
              "RelativeToolTip": "PdmSwPlugin.Main\\Constant\\PluginConst.cs",
              "ViewState": "AgIAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-10-14T04:01:41.756Z",
              "EditorCaption": ""
            },
            {
              "$type": "Document",
              "DocumentIndex": 2,
              "Title": "PdmBom.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Common\\Entity\\Pdm\\PdmBom.cs",
              "RelativeDocumentMoniker": "PdmSwPlugin.Common\\Entity\\Pdm\\PdmBom.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Common\\Entity\\Pdm\\PdmBom.cs",
              "RelativeToolTip": "PdmSwPlugin.Common\\Entity\\Pdm\\PdmBom.cs",
              "ViewState": "AgIAAIgAAAAAAAAAAAA+wJYAAAAdAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-10-31T08:32:38.632Z"
            },
            {
              "$type": "Document",
              "DocumentIndex": 6,
              "Title": "MainWindow.xaml.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\Md5Reader\\MainWindow.xaml.cs",
              "RelativeDocumentMoniker": "Md5Reader\\MainWindow.xaml.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\Md5Reader\\MainWindow.xaml.cs",
              "RelativeToolTip": "Md5Reader\\MainWindow.xaml.cs",
              "ViewState": "AgIAAAAAAAAAAAAAAAAAABAAAABDAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-10-30T02:39:22.183Z"
            },
            {
              "$type": "Document",
              "DocumentIndex": 7,
              "Title": "MainControl.xaml.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Main\\MainControl.xaml.cs",
              "RelativeDocumentMoniker": "PdmSwPlugin.Main\\MainControl.xaml.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\PdmSwPlugin.Main\\MainControl.xaml.cs",
              "RelativeToolTip": "PdmSwPlugin.Main\\MainControl.xaml.cs",
              "ViewState": "AgIAAMAAAAAAAAAAAAAYwMoAAAAAAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-10-14T04:24:56.766Z"
            },
            {
              "$type": "Document",
              "DocumentIndex": 8,
              "Title": "Listener.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\SolidWorksListener\\Listener.cs",
              "RelativeDocumentMoniker": "SolidWorksListener\\Listener.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\SolidWorksListener\\Listener.cs",
              "RelativeToolTip": "SolidWorksListener\\Listener.cs",
              "ViewState": "AgIAANAAAAAAAAAAAADwv90AAAAiAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-10-14T03:42:50.289Z"
            },
            {
              "$type": "Document",
              "DocumentIndex": 9,
              "Title": "AsyncAttacher.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\WpfUI\\AsyncAttacher.cs",
              "RelativeDocumentMoniker": "WpfUI\\AsyncAttacher.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\WpfUI\\AsyncAttacher.cs",
              "RelativeToolTip": "WpfUI\\AsyncAttacher.cs",
              "ViewState": "AgIAAAAAAAAAAAAAAAAAAA8AAAAJAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-10-14T03:36:12.415Z"
            },
            {
              "$type": "Document",
              "DocumentIndex": 10,
              "Title": "SwAddin.cs",
              "DocumentMoniker": "D:\\Workspace\\PdmSwPlugin2\\PdmSw\\SwAddin.cs",
              "RelativeDocumentMoniker": "PdmSw\\SwAddin.cs",
              "ToolTip": "D:\\Workspace\\PdmSwPlugin2\\PdmSw\\SwAddin.cs",
              "RelativeToolTip": "PdmSw\\SwAddin.cs",
              "ViewState": "AgIAABMBAAAAAAAAAAAkwCYBAAAkAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2024-10-14T01:09:55.509Z"
            }
          ]
        }
AutoUpdater/MainWindow.xaml.cs
@@ -2,12 +2,12 @@
using AutoUpdater.Util;
using ICSharpCode.SharpZipLib.Zip;
using log4net;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows;
using VersionControl;
@@ -130,20 +130,27 @@
        /// </summary>
        public void StartListenerProcess()
        {
            string dir = Path.GetDirectoryName(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
            string path1 = Path.Combine(dir, "Listener", "SolidWorksListener.exe");
            if (File.Exists(path1))
            try
            {
                ProcessStartInfo info = new ProcessStartInfo
                string dir = Path.GetDirectoryName(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
                string path1 = Path.Combine(dir, "Listener", "SolidWorksListener.exe");
                if (File.Exists(path1))
                {
                    FileName = path1,
                    WorkingDirectory = Path.GetDirectoryName(path1)
                };
                    ProcessStartInfo info = new ProcessStartInfo
                    {
                        FileName = path1,
                        WorkingDirectory = Path.GetDirectoryName(path1)
                    };
                new Process
                {
                    StartInfo = info
                }.Start();
                    new Process
                    {
                        StartInfo = info
                    }.Start();
                }
            }
            catch (Exception ex)
            {
                Logger.Error("Start Listener Process Error!", ex);
            }
        }
@@ -330,10 +337,60 @@
            DoFinished();
        }
        private void DoFinished()
        /// <summary>
        /// 检查自启动注册表
        /// </summary>
        private void CheckAutoRunRegKey()
        {
            RegistryKey root = null;
            RegistryKey key = null;
            try
            {
                root = Registry.CurrentUser;
                key = root.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);
                string name = "SolidWorksListener";
                if (key == null)
                {
                    key = root.CreateSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run");
                }
                // 没有路径或者路径指向exe不对,就更新自启动路径
                string listenerPath = key.GetValue(name)?.ToString();
                string rootDir = new DirectoryInfo(Assembly.GetExecutingAssembly().Location).Parent.Parent.FullName;
                string newPath = Path.Combine(rootDir, "Listener", "SolidWorksListener.exe");
                //listenerPath = listenerPath.Replace("\"", "");
                if (string.IsNullOrEmpty(listenerPath) || new Uri(listenerPath) != new Uri(newPath))
                {
                    key.SetValue(name, newPath, RegistryValueKind.String);
                }
            }
            catch (Exception e)
            {
                Logger.Error("CheckAutoRunRegKey Failed!", e);
            }
            finally
            {
                try
                {
                    if (key != null) key.Close();
                    if (root != null) root.Close();
                }
                catch (Exception ex)
                {
                    Logger.Error("Reg Key Close Failed!", ex);
                }
            }
        }
        private void BeforeRestart()
        {
            CheckAutoRunRegKey();
            // 启动监听进程
            StartListenerProcess();
        }
        private void DoFinished()
        {
            BeforeRestart();
            label.Content = "更新完成";
            bar.IsIndeterminate = false;
            if (SwAppPath != null)
InnoSetupScript/PdmSwPlugin.iss
@@ -7,7 +7,7 @@
; 自动更新程序路径
#define AutoUpdaterDir = "D:\Workspace\PdmSwPlugin2\PdmSw\bin\x64\Release\AutoUpdater\"
; 版本
#define Version = "_0.0.0.42"
#define Version = "_0.0.0.43_改"
; 生成的Installer存放路径
#define OutPutDir = "Z:\Output"
@@ -81,7 +81,7 @@
;Root: HKLM64; Subkey: "SYSTEM\CurrentControlSet\Services\SolidWorks Listener"; ValueType: dword; ValueName: "Type"; ValueData: 272; Flags: deletevalue
; 监听器2.0
Root: HKCU64; Subkey: "SOFTWARE\Microsoft\Windows\CurrentVersion\Run"; ValueType: string; ValueName: "SolidWorksListener"; ValueData: """{app}\Listener\SolidWorksListener.exe"""; Flags: deletevalue uninsdeletevalue
Root: HKCU64; Subkey: "SOFTWARE\Microsoft\Windows\CurrentVersion\Run"; ValueType: string; ValueName: "SolidWorksListener"; ValueData: "{app}\Listener\SolidWorksListener.exe"; Flags: deletevalue uninsdeletevalue
 
[Icons]
Md5Reader/App.config
New file
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
    </startup>
</configuration>
Md5Reader/App.xaml
New file
@@ -0,0 +1,9 @@
<Application x:Class="Md5Reader.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:Md5Reader"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
    </Application.Resources>
</Application>
Md5Reader/App.xaml.cs
New file
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace Md5Reader
{
    /// <summary>
    /// App.xaml 的交互逻辑
    /// </summary>
    public partial class App : Application
    {
    }
}
Md5Reader/MainWindow.xaml
New file
@@ -0,0 +1,22 @@
<Window x:Class="Md5Reader.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Md5Reader"
        mc:Ignorable="d"
        Title="MD5工具" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Button Grid.Row="0" Grid.Column="0"  Padding="20" Click="Button_Click">打开文件</Button>
        <TextBox Grid.Row="0" Grid.Column="1" IsReadOnly="True" x:Name="pathInput"></TextBox>
        <TextBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" IsReadOnly="True" TextWrapping="WrapWithOverflow" x:Name="consoleInput"></TextBox>
    </Grid>
</Window>
Md5Reader/MainWindow.xaml.cs
New file
@@ -0,0 +1,29 @@
using PdmSwPlugin.Common.Util;
using System.Windows;
using System.Windows.Forms;
namespace Md5Reader
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Multiselect = false;
            if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                pathInput.Text = openFileDialog.FileName;
                string md5 = MD5Util.Md5SHA1(openFileDialog.FileName);
                consoleInput.Text += $"文件路径: {openFileDialog.FileName}\r\nMD5: {md5}\r\n\r\n";
            }
        }
    }
}
Md5Reader/Md5Reader.csproj
New file
@@ -0,0 +1,125 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{3AEC586C-B22A-4ADB-B4AB-10AA660F79EC}</ProjectGuid>
    <OutputType>WinExe</OutputType>
    <RootNamespace>Md5Reader</RootNamespace>
    <AssemblyName>Md5Reader</AssemblyName>
    <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
    <WarningLevel>4</WarningLevel>
    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
    <Deterministic>true</Deterministic>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
    <DebugSymbols>true</DebugSymbols>
    <OutputPath>bin\x64\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <DebugType>full</DebugType>
    <PlatformTarget>x64</PlatformTarget>
    <LangVersion>7.3</LangVersion>
    <ErrorReport>prompt</ErrorReport>
    <Prefer32Bit>true</Prefer32Bit>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
    <OutputPath>bin\x64\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <Optimize>true</Optimize>
    <DebugType>pdbonly</DebugType>
    <PlatformTarget>x64</PlatformTarget>
    <LangVersion>7.3</LangVersion>
    <ErrorReport>prompt</ErrorReport>
    <Prefer32Bit>true</Prefer32Bit>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Data" />
    <Reference Include="System.Windows.Forms" />
    <Reference Include="System.Xml" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Core" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="System.Net.Http" />
    <Reference Include="System.Xaml">
      <RequiredTargetFramework>4.0</RequiredTargetFramework>
    </Reference>
    <Reference Include="WindowsBase" />
    <Reference Include="PresentationCore" />
    <Reference Include="PresentationFramework" />
  </ItemGroup>
  <ItemGroup>
    <ApplicationDefinition Include="App.xaml">
      <Generator>MSBuild:Compile</Generator>
      <SubType>Designer</SubType>
    </ApplicationDefinition>
    <Page Include="MainWindow.xaml">
      <Generator>MSBuild:Compile</Generator>
      <SubType>Designer</SubType>
    </Page>
    <Compile Include="App.xaml.cs">
      <DependentUpon>App.xaml</DependentUpon>
      <SubType>Code</SubType>
    </Compile>
    <Compile Include="MainWindow.xaml.cs">
      <DependentUpon>MainWindow.xaml</DependentUpon>
      <SubType>Code</SubType>
    </Compile>
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Properties\AssemblyInfo.cs">
      <SubType>Code</SubType>
    </Compile>
    <Compile Include="Properties\Resources.Designer.cs">
      <AutoGen>True</AutoGen>
      <DesignTime>True</DesignTime>
      <DependentUpon>Resources.resx</DependentUpon>
    </Compile>
    <Compile Include="Properties\Settings.Designer.cs">
      <AutoGen>True</AutoGen>
      <DependentUpon>Settings.settings</DependentUpon>
      <DesignTimeSharedInput>True</DesignTimeSharedInput>
    </Compile>
    <EmbeddedResource Include="Properties\Resources.resx">
      <Generator>ResXFileCodeGenerator</Generator>
      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
    </EmbeddedResource>
    <None Include="Properties\Settings.settings">
      <Generator>SettingsSingleFileGenerator</Generator>
      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
    </None>
  </ItemGroup>
  <ItemGroup>
    <None Include="App.config" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\PdmSwPlugin.Common\PdmSwPlugin.Common.csproj">
      <Project>{e17ef6b6-ee83-45aa-b0c0-e3a097089e97}</Project>
      <Name>PdmSwPlugin.Common</Name>
    </ProjectReference>
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
Md5Reader/Properties/AssemblyInfo.cs
New file
@@ -0,0 +1,52 @@
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("Md5Reader")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Md5Reader")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 会使此程序集中的类型
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
//请将此类型的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
//若要开始生成可本地化的应用程序,请设置
//.csproj 文件中的 <UICulture>CultureYouAreCodingWith</UICulture>
//在 <PropertyGroup> 中。例如,如果你使用的是美国英语。
//使用的是美国英语,请将 <UICulture> 设置为 en-US。  然后取消
//对以下 NeutralResourceLanguage 特性的注释。  更新
//以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
    ResourceDictionaryLocation.None, //主题特定资源词典所处位置
                                     //(未在页面中找到资源时使用,
                                     //或应用程序资源字典中找到时使用)
    ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
                                              //(未在页面中找到资源时使用,
                                              //、应用程序或任何主题专用资源字典中找到时使用)
)]
// 程序集的版本信息由下列四个值组成:
//
//      主版本
//      次版本
//      生成号
//      修订号
//
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Md5Reader/Properties/Resources.Designer.cs
New file
@@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
//     此代码由工具生成。
//     运行时版本: 4.0.30319.42000
//
//     对此文件的更改可能导致不正确的行为,如果
//     重新生成代码,则所做更改将丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace Md5Reader.Properties
{
    /// <summary>
    ///   强类型资源类,用于查找本地化字符串等。
    /// </summary>
    // 此类是由 StronglyTypedResourceBuilder
    // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
    // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
    // (以 /str 作为命令选项),或重新生成 VS 项目。
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    internal class Resources
    {
        private static global::System.Resources.ResourceManager resourceMan;
        private static global::System.Globalization.CultureInfo resourceCulture;
        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
        internal Resources()
        {
        }
        /// <summary>
        ///   返回此类使用的缓存 ResourceManager 实例。
        /// </summary>
        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
        internal static global::System.Resources.ResourceManager ResourceManager
        {
            get
            {
                if ((resourceMan == null))
                {
                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Md5Reader.Properties.Resources", typeof(Resources).Assembly);
                    resourceMan = temp;
                }
                return resourceMan;
            }
        }
        /// <summary>
        ///   重写当前线程的 CurrentUICulture 属性,对
        ///   使用此强类型资源类的所有资源查找执行重写。
        /// </summary>
        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
        internal static global::System.Globalization.CultureInfo Culture
        {
            get
            {
                return resourceCulture;
            }
            set
            {
                resourceCulture = value;
            }
        }
    }
}
Md5Reader/Properties/Resources.resx
New file
@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
  <!--
    Microsoft ResX Schema
    Version 2.0
    The primary goals of this format is to allow a simple XML format
    that is mostly human readable. The generation and parsing of the
    various data types are done through the TypeConverter classes
    associated with the data types.
    Example:
    ... ado.net/XML headers & schema ...
    <resheader name="resmimetype">text/microsoft-resx</resheader>
    <resheader name="version">2.0</resheader>
    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
        <value>[base64 mime encoded serialized .NET Framework object]</value>
    </data>
    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
        <comment>This is a comment</comment>
    </data>
    There are any number of "resheader" rows that contain simple
    name/value pairs.
    Each data row contains a name, and value. The row also contains a
    type or mimetype. Type corresponds to a .NET class that support
    text/value conversion through the TypeConverter architecture.
    Classes that don't support this are serialized and stored with the
    mimetype set.
    The mimetype is used for serialized objects, and tells the
    ResXResourceReader how to depersist the object. This is currently not
    extensible. For a given mimetype the value must be set accordingly:
    Note - application/x-microsoft.net.object.binary.base64 is the format
    that the ResXResourceWriter will generate, however the reader can
    read any of the formats listed below.
    mimetype: application/x-microsoft.net.object.binary.base64
    value   : The object must be serialized with
            : System.Serialization.Formatters.Binary.BinaryFormatter
            : and then encoded with base64 encoding.
    mimetype: application/x-microsoft.net.object.soap.base64
    value   : The object must be serialized with
            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
            : and then encoded with base64 encoding.
    mimetype: application/x-microsoft.net.object.bytearray.base64
    value   : The object must be serialized into a byte array
            : using a System.ComponentModel.TypeConverter
            : and then encoded with base64 encoding.
    -->
  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xsd:element name="root" msdata:IsDataSet="true">
      <xsd:complexType>
        <xsd:choice maxOccurs="unbounded">
          <xsd:element name="metadata">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" />
              <xsd:attribute name="type" type="xsd:string" />
              <xsd:attribute name="mimetype" type="xsd:string" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="assembly">
            <xsd:complexType>
              <xsd:attribute name="alias" type="xsd:string" />
              <xsd:attribute name="name" type="xsd:string" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="data">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="resheader">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" />
            </xsd:complexType>
          </xsd:element>
        </xsd:choice>
      </xsd:complexType>
    </xsd:element>
  </xsd:schema>
  <resheader name="resmimetype">
    <value>text/microsoft-resx</value>
  </resheader>
  <resheader name="version">
    <value>2.0</value>
  </resheader>
  <resheader name="reader">
    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <resheader name="writer">
    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
</root>
Md5Reader/Properties/Settings.Designer.cs
New file
@@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.42000
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Md5Reader.Properties
{
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
    {
        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
        public static Settings Default
        {
            get
            {
                return defaultInstance;
            }
        }
    }
}
Md5Reader/Properties/Settings.settings
New file
@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
  <Profiles>
    <Profile Name="(Default)" />
  </Profiles>
  <Settings />
</SettingsFile>
PdmSw/SwAddin.cs
@@ -126,6 +126,8 @@
        private BaseAttacher attacher;
        private ISldWorks swApp;
        private TaskpaneView panel;
        private Form mainForm;
        // Public Properties
        public ISldWorks SwApp
        {
@@ -274,7 +276,7 @@
                    Path.Combine(imageFolder, @"MatChooser_128X128.png")
            };
            // 创建Panel
            TaskpaneView panel = SwApp.CreateTaskpaneView3(bitmaps, "PdmSwPlugin" + PluginConst.Version);
            panel = SwApp.CreateTaskpaneView3(bitmaps, "PdmSwPlugin" + PluginConst.Version);
            mainControl = new MainControl((SldWorks)SwApp);
            // 只能用winform,代理wpf
@@ -284,7 +286,7 @@
                AutoSize = true,
                Dock = DockStyle.Fill
            };
            Form form = new Form
            mainForm = new Form
            {
                Text = "PdmSwPlugin",
                ControlBox = false,
@@ -292,10 +294,11 @@
                KeyPreview = true,
                Dock = DockStyle.Fill
            };
            form.Controls.Add(host);
            IntPtr ptr = form.Handle;
            mainForm.Controls.Add(host);
            IntPtr ptr = mainForm.Handle;
            // IntPtr ptr = WindowIntPtrUtil.FindWindow(null, "Window1");
            panel.DisplayWindowFromHandlex64(ptr.ToInt64());
            mainForm.WindowState = FormWindowState.Maximized;
        }
        private void LoadPlugins()
@@ -327,23 +330,36 @@
        /// <returns></returns>
        public bool DisconnectFromSW()
        {
            RemoveCommandMgr();
            RemovePMP();
            mainControl.StopTcpServer();
            attacher.DetachEventHandlers();
            attacher = null;
            try
            {
                RemoveCommandMgr();
                RemovePMP();
                mainControl.StopTcpServer();
                mainControl.DeActiveHandler();
                attacher.DetachEventHandlers();
                attacher = null;
            System.Runtime.InteropServices.Marshal.ReleaseComObject(iCmdMgr);
            iCmdMgr = null;
            System.Runtime.InteropServices.Marshal.ReleaseComObject(SwApp);
            swApp = null;
            //The addin _must_ call GC.Collect() here in order to retrieve all managed code pointers
            GC.Collect();
            GC.WaitForPendingFinalizers();
                mainForm.Close();
                mainForm = null;
                mainControl = null;
                panel.DeleteView();
                panel = null;
            GC.Collect();
            GC.WaitForPendingFinalizers();
                Marshal.ReleaseComObject(iCmdMgr);
                iCmdMgr = null;
                Marshal.ReleaseComObject(SwApp);
                swApp = null;
                //The addin _must_ call GC.Collect() here in order to retrieve all managed code pointers
                GC.Collect();
                GC.WaitForPendingFinalizers();
                //GC.Collect();
                //GC.WaitForPendingFinalizers();
            }
            catch (Exception ex)
            {
                Logger.Error("DisconnectFromSW Failed!", ex);
            }
            return true;
        }
        #endregion
PdmSwPlugin.Common/BomIniter/NameUtil.cs
@@ -5,8 +5,6 @@
{
    public class NameUtil
    {
        public static readonly PluginSetting setting = PluginSetting.Instance;
        /// <summary>
        /// 判断文档是否是历史文档
        /// </summary>
@@ -14,12 +12,15 @@
        /// <returns>true 是 false 不是</returns>
        public static bool IsHistoryDoc(string name)
        {
            CustomerSetting setting = CustomerSetting.Instance;
            if (string.IsNullOrEmpty(name)) return false;
            if (setting.HistoryDateFlag < 0) return false;
            string historyFlagStr = setting["historyFlag"];
            _ = long.TryParse(historyFlagStr, out long flag);
            if (flag < 0) return false;
            try
            {
                long historyFlag = long.Parse(name.Substring(0, 8));
                if (historyFlag <= setting.HistoryDateFlag)
                if (historyFlag <= flag)
                {
                    return true;
                }
PdmSwPlugin.Common/BomIniter/YwtBomIniter.cs
@@ -10,8 +10,6 @@
    public class YwtBomIniter : BomIniter
    {
        public static PluginSetting setting = PluginSetting.Instance;
        public string jgjNameRegx { get; private set; } = CustomerSetting.Instance["jgjNameRegx"];
        public string standardNameRegx { get; private set; } = CustomerSetting.Instance["standardNameRegx"];
        public void InitBom(PdmBom bom)
        {
@@ -27,16 +25,20 @@
            bom.xc = false;
            bom.mn = false;
            string jgjNameRegx = CustomerSetting.Instance["jgjNameRegx"];
            string standardNameRegx = CustomerSetting.Instance["standardNameRegx"];
            if (Regex.IsMatch(childName, jgjNameRegx))
            {
                if (bom._drawInfo != null) {
                if (bom._drawInfo != null)
                {
                    bom._drawInfo.HistoryData = NameUtil.IsHistoryDoc(childName);
                }
                string docType = bom.properties.Get("文件格式");
                if (string.IsNullOrEmpty(docType))
                {
                    bom.produceWay = "标准件";
                    bom.produceWay = "加工件";
                }
                else
                {
@@ -72,12 +74,14 @@
        /// <returns></returns>
        public bool IsJgjPanel(ModelDoc2 doc)
        {
            string jgjNameRegx = CustomerSetting.Instance["jgjNameRegx"];
            string fileName = Path.GetFileNameWithoutExtension(doc.GetPathName());
            return Regex.IsMatch(fileName, jgjNameRegx);
        }
        public bool IsJgj(ModelDoc2 doc)
        {
            string jgjNameRegx = CustomerSetting.Instance["jgjNameRegx"];
            string fileName = Path.GetFileNameWithoutExtension(doc.GetPathName());
            return Regex.IsMatch(fileName, jgjNameRegx);
        }
@@ -85,6 +89,8 @@
        public bool IsStandard(ModelDoc2 doc)
        {
            string fileName = doc.GetPathName();
            string standardNameRegx = CustomerSetting.Instance["standardNameRegx"];
            fileName = Path.GetFileNameWithoutExtension(fileName);
            return Regex.IsMatch(fileName, standardNameRegx);
        }
PdmSwPlugin.Common/Control/RichHisWindow.xaml
@@ -11,9 +11,9 @@
             Height="600" Width="1200">
    <DataGrid x:Name="table" ItemsSource="{Binding HisList}"
          AutoGenerateColumns="False"
            EnableRowVirtualization="False"
            CanUserAddRows="False"
            ColumnWidth="*"
            ScrollViewer.CanContentScroll="False"
            CanUserSortColumns="False"
            CanUserDeleteRows="False">
        <DataGrid.Columns>
PdmSwPlugin.Common/Control/RichHisWindow.xaml.cs
@@ -62,6 +62,7 @@
            else
            {
                this.HisList = new ObservableCollection<DrawAuditHis>(hisList);
                table.ScrollIntoView(HisList[0]);
            }
        }
PdmSwPlugin.Common/Entity/Pdm/PdmBom.cs
@@ -43,6 +43,7 @@
        public Component2 component { get; set; }
        public bool lost { get; set; } = false;
        public bool isHidden { get; set; } = false;
        public bool suppressed { get; set; } = false;
        public bool lightWeight { get; set; } = false;
@@ -147,6 +148,8 @@
        private int? _checkRuleResult = 0;
        public bool isHidden;
        public int? checkRuleResult
        {
            get => _checkRuleResult;
@@ -204,7 +207,10 @@
        public Dictionary<string, string> properties => BomInfo?.properties;
        public string d3FilePath => BomInfo?.d3FilePath;
        public string filePath => BomInfo?.filePath;
        public bool lost => BomInfo?.lost == true;
        public bool lost => BomInfo?.lost == true || isHidden;
        public bool isHidden = false;
        public bool suppressed => BomInfo?.suppressed == true;
        public bool lightWeight => BomInfo?.lightWeight == true;
@@ -243,7 +249,7 @@
        /// <summary>
        /// 规则检查结果
        /// </summary>
        public int? checkRuleResult => (IsHistoryData || skipCheck) ? 3 : _drawInfo?.checkRuleResult;
        public int? checkRuleResult => (IsHistoryData || skipCheck) ? 3 : (isHidden ? 2 : _drawInfo?.checkRuleResult);
        /// <summary>
        /// 检查是否OK
        /// </summary>
@@ -260,6 +266,8 @@
            }
        }
        public List<string> ErrorMsgs;
        /// <summary>
        /// 是否需要审核
        /// </summary>
@@ -273,7 +281,7 @@
                if (ExcludeFromBOM) return false;
                // 模组不审核
                if (produceWay == "模组") return false;
                // 待审核的不冲突提交
                // 待审核的不重复提交
                if (drawStatus == "submitted" || drawStatus == "resubmitted") return false;
                if (IsHistoryData)
                {
@@ -300,14 +308,25 @@
            if (ExcludeFromBOM) return null;
            if (IsHistoryData)
            {
                bool err = false;
                string msg = $"历史图纸【{partModel}】";
                if (localDocChanged)
                {
                    return $"历史图纸【{partModel}】变更后未重新审核";
                    err = true;
                    msg += "变更后未重新审核;";
                }
                else if (drawStatus == "rejected" || drawStatus == "submitted" || drawStatus == "resubmitted")
                {
                    return $"历史图纸【{partModel}】未通过审核";
                    err = true;
                    msg += "未通过审核";
                }
                if (isHidden)
                {
                    err = true;
                    msg += "被隐藏;";
                }
                return err ? msg : null;
            }
            if (!IsHistoryData)
            {
@@ -316,7 +335,12 @@
                if (!skipCheck && !checkRuleOk)
                {
                    error = true;
                    msg += "未通过规则检查";
                    msg += "未通过规则检查;";
                }
                if (!skipCheck && isHidden)
                {
                    error = true;
                    msg += "被隐藏;";
                }
                if (produceWay == "加工件" && drawStatus != "completed")
                {
PdmSwPlugin.Common/Setting/CustomerSetting.cs
@@ -16,10 +16,7 @@
        public static void Set(Dictionary<string, string> Settings)
        {
            if (Instance == null)
            {
                Instance = new CustomerSetting(Settings);
            }
            Instance = new CustomerSetting(Settings);
        }
        public string this[string field]
PdmSwPlugin.Common/Util/CustomPropertyUtil.cs
@@ -31,6 +31,13 @@
            }
        }
        /// <summary>
        /// 获取文档属性
        /// </summary>
        /// <param name="currentModelDoc">文档</param>
        /// <param name="needResolve">是否转换值</param>
        /// <param name="skipName">跳过的name</param>
        /// <returns></returns>
        public static Dictionary<string, string> GetCustomProperties2(ModelDoc2 currentModelDoc,
            bool needResolve,
            HashSet<string> skipName = null)
PdmSwPlugin.Common/Util/LimitedConcurrencyLevelTaskScheduler.cs
@@ -8,15 +8,15 @@
    /// <summary>
    /// https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.tasks.taskscheduler?view=netframework-4.7.2
    /// </summary>
    public class LimitedConcurrencyLevelTaskScheduler : TaskScheduler
    public class LimitedConcurrencyLevelTaskSchedulerMsn : TaskScheduler
    {
        public static LimitedConcurrencyLevelTaskScheduler Instance { get; private set; }
        public static LimitedConcurrencyLevelTaskSchedulerMsn Instance { get; private set; }
        public static TaskFactory Factory { get; private set; }
        static LimitedConcurrencyLevelTaskScheduler()
        static LimitedConcurrencyLevelTaskSchedulerMsn()
        {
            Instance = new LimitedConcurrencyLevelTaskScheduler(Environment.ProcessorCount * 10);
            Instance = new LimitedConcurrencyLevelTaskSchedulerMsn(Environment.ProcessorCount * 10);
            Factory = new TaskFactory(Instance);
        }
@@ -34,7 +34,7 @@
        private int _delegatesQueuedOrRunning = 0;
        // Creates a new instance with the specified degree of parallelism.
        public LimitedConcurrencyLevelTaskScheduler(int maxDegreeOfParallelism)
        public LimitedConcurrencyLevelTaskSchedulerMsn(int maxDegreeOfParallelism)
        {
            if (maxDegreeOfParallelism < 1) throw new ArgumentOutOfRangeException("maxDegreeOfParallelism");
            _maxDegreeOfParallelism = maxDegreeOfParallelism;
PdmSwPlugin.Common/Util/Pdm/BomTreeReader.cs
@@ -16,7 +16,7 @@
    {
        public BomTreeReader()
        {
            factory = LimitedConcurrencyLevelTaskScheduler.Factory;
            factory = LimitedConcurrencyLevelTaskSchedulerMsn.Factory;
        }
        public TaskFactory factory;
@@ -260,6 +260,10 @@
        private static PdmBom ConcatCacheBom(BomInfo info, int level, PdmBom parent, Component2 component)
        {
            if (info == null) return null;
            //if (component.IsHidden(true))
            //{
            //    info.isHidden = true;
            //}
            PdmBom bom = new PdmBom
            {
                BomInfo = info,
@@ -267,7 +271,8 @@
                level = level,
                quantity = 1,
                parent = parent,
                component = component
                component = component,
                isHidden = component.IsHidden(true)
            };
            // 封装Bom信息
            bom.Init();
PdmSwPlugin.DrawApprove/DrawApprove.xaml.cs
@@ -260,16 +260,24 @@
        private void OpenDrw_Click(object sender, RoutedEventArgs e)
        {
            Button btn = sender as Button;
            DrawAudit da = btn.DataContext as DrawAudit;
            string filePath = GetRealFilePath(da.d2RelativePath);
            if (!File.Exists(filePath))
            try
            {
                this.Error($"服务器中未找到工程图文件,路径:{filePath}");
                return;
                Button btn = sender as Button;
                DrawAudit da = btn.DataContext as DrawAudit;
                string filePath = GetRealFilePath(da.d2RelativePath);
                if (!File.Exists(filePath))
                {
                    this.Error($"服务器中未找到工程图文件,路径:{filePath}");
                    return;
                }
                OpenDocMayError(filePath, (int)swDocumentTypes_e.swDocDRAWING, (int)swOpenDocOptions_e.swOpenDocOptions_ReadOnly,
                    "");
            }
            OpenDocMayError(filePath, (int)swDocumentTypes_e.swDocDRAWING, (int)swOpenDocOptions_e.swOpenDocOptions_ReadOnly,
                "");
            catch (Exception ex)
            {
                this.Error($"打开工程图异常!{ex}");
                Logger.Error("Open Drw Error!", ex);
            }
        }
        private string GetRealFilePath(string relativePath)
@@ -282,17 +290,25 @@
        private void OpenDoc_Click(object sender, RoutedEventArgs e)
        {
            Button btn = sender as Button;
            DrawAudit da = btn.DataContext as DrawAudit;
            string filePath = GetRealFilePath(da.d3RelativePath);
            if (!File.Exists(filePath))
            try
            {
                this.Error($"服务器中未找到图纸文件,路径:{filePath}");
                return;
            }
                Button btn = sender as Button;
                DrawAudit da = btn.DataContext as DrawAudit;
                string filePath = GetRealFilePath(da.d3RelativePath);
                if (!File.Exists(filePath))
                {
                    this.Error($"服务器中未找到图纸文件,路径:{filePath}");
                    return;
                }
            OpenDocMayError(filePath, (int)FileExtentionChecker.Check(filePath, out _), (int)swOpenDocOptions_e.swOpenDocOptions_ReadOnly,
                 "");
                OpenDocMayError(filePath, (int)FileExtentionChecker.Check(filePath, out _), (int)swOpenDocOptions_e.swOpenDocOptions_ReadOnly,
                     "");
            }
            catch (Exception ex)
            {
                this.Error($"打开图纸异常!{ex}");
                Logger.Error("Open 3D Doc Error!", ex);
            }
        }
        public List<DrawAudit> RefreshList()
PdmSwPlugin.Main/Constant/PluginConst.cs
@@ -3,6 +3,6 @@
    public class PluginConst
    {
        public static readonly string AppId = "DF23E96F-A469-4302-8367-7FA2F798CD09";
        public static readonly string Version = "0.0.0.42";
        public static readonly string Version = "0.0.0.44";
    }
}
PdmSwPlugin.Main/MainControl.xaml.cs
@@ -18,6 +18,8 @@
using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Protocol;
using PdmSwPlugin.Main.Tcp;
using SolidWorks.Interop.swconst;
using System.Windows.Interop;
namespace PdmSwPlugin.Main
{
@@ -121,6 +123,20 @@
            string updaterPath = "AutoUpdater\\AutoUpdater.exe";
            string exePath = new DirectoryInfo(Assembly.GetExecutingAssembly().Location).Parent.FullName;
            string exeFileName = $"{exePath}\\{updaterPath}";
            //if (SwApp.SendMsgToUser2("检测到插件更新,是否立刻更新?(请注意保存当前工作)", (int)swMessageBoxIcon_e.swMbInformation, (int)swMessageBoxBtn_e.swMbYesNo)
            //    == (int)swMessageBoxResult_e.swMbHitYes)
            //{
            //    Process updaterProcess = new Process
            //    {
            //        StartInfo = new ProcessStartInfo
            //        {
            //            FileName = exeFileName,
            //            Arguments = mainProcessId + ""
            //        }
            //    };
            //    updaterProcess.Start();
            //}
            // 非必要更新
            new Task(() =>
            {
@@ -209,9 +225,29 @@
        public void Logout()
        {
            string binPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData), "HengXin", "PdmSwPlugin", "bin");
            File.Delete(binPath);
            DeActiveHandler();
            try
            {
                // 删除缓存bin文件
                string binPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData), "HengXin", "PdmSwPlugin", "bin");
                File.Delete(binPath);
            }
            catch (Exception ex)
            {
                //SwApp.SendMsgToUser2("用户缓存清理失败!", (int)swMessageBoxIcon_e.swMbWarning, (int)swMessageBoxBtn_e.swMbOk);
                Logger.Error("Delete User Bin File Failed.", ex);
            }
            try
            {
                // 清除UserControl事件
                DeActiveHandler();
            }
            catch (Exception ex)
            {
                SwApp.SendMsgToUser2("发生未知异常,详情请见日志!", (int)swMessageBoxIcon_e.swMbWarning, (int)swMessageBoxBtn_e.swMbOk);
                Logger.Error("DeActiveHandler Failed.", ex);
            }
            mainTab.tabControl.Items.Clear();
            PdmUser.SetLoginUser(null);
            mainBorder.Child = new LoginControl(LoginSuccess);
@@ -238,7 +274,7 @@
        private void self_Unloaded(object sender, RoutedEventArgs e)
        {
            StopTcpServer();
            // StopTcpServer();
        }
    }
}
PdmSwPlugin.Main/MainTab.xaml
@@ -19,9 +19,12 @@
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <TabControl Grid.Row="0" x:Name="tabControl"></TabControl>
        <StatusBar Grid.Row="1" Padding="0" Margin="0" VerticalContentAlignment="Center">
            <Label x:Name="userLabel" FontWeight="Bold" Padding="0" Margin="0" />
            <Button Style="{StaticResource LinkButton}" Click="Button_Click">退出登录</Button>
        </StatusBar>
        <DockPanel Grid.Row="1" Margin="0" LastChildFill="False">
            <Label DockPanel.Dock="Left" x:Name="userLabel" FontWeight="Bold" Padding="0" Margin="0,0,20,0" />
            <Button DockPanel.Dock="Left" Style="{StaticResource LinkButton}" Click="Button_Click">退出登录</Button>
            <Button DockPanel.Dock="Right" Style="{StaticResource LinkButton}" Margin="0,0,20,0"  Click="Refresh_Click">刷新</Button>
            <Label DockPanel.Dock="Right" x:Name="configLabel" FontWeight="Bold" Padding="0" Margin="0,0,20,0" />
            <Label DockPanel.Dock="Right" FontWeight="Bold" Padding="0"  Content="历史节点:" />
        </DockPanel>
    </Grid>
</UserControl>
PdmSwPlugin.Main/MainTab.xaml.cs
@@ -5,6 +5,10 @@
using System.Windows;
using System.Windows.Controls;
using SolidWorks.Interop.swconst;
using PdmSwPlugin.Common.Setting;
using System.Threading.Tasks;
using PdmSwPlugin.Common.Util.Http;
using System.Collections.Generic;
namespace PdmSwPlugin.Main
{
@@ -19,6 +23,7 @@
            this.logout = logout;
            InitializeComponent();
            userLabel.Content = $"欢迎您,{PdmUser.LoginUser?.realname}";
            configLabel.Content = CustomerSetting.Instance["historyFlag"];
        }
        private SldWorks swApp;
@@ -37,5 +42,30 @@
                logout();
            }
        }
        private void Refresh_Click(object sender, RoutedEventArgs e)
        {
            configLabel.Content = "刷新中...";
            Task.Run(() =>
            {
                try
                {
                    Result<Dictionary<string, string>> res = HttpClientCreator.PostSyncAction<Dictionary<string, string>>("openApi/wpf/refreshConfig", null);
                    Dictionary<string, string> setting = res.HandleResult();
                    CustomerSetting.Set(setting);
                }
                catch (Exception ex)
                {
                }
                finally
                {
                    Dispatcher.Invoke(() =>
                    {
                        configLabel.Content = CustomerSetting.Instance["historyFlag"];
                    });
                }
            });
        }
    }
}
PdmSwPlugin.Main/SwAddIn/MainControl.cs
@@ -17,6 +17,9 @@
using PdmSwPlugin.MaterialSelect;
using PdmSwPlugin.PriceCheck;
using PdmSwPlugin.Common.Setting;
using Microsoft.Win32;
using System.IO;
using System.Diagnostics;
namespace PdmSwPlugin.Main
{
@@ -28,7 +31,7 @@
    {
        public SldWorks SwApp { get; private set; }
        private ILog Logger = LogManager.GetLogger("Main");
        private ILog Logger;
        private PluginSetting GlobalConfig;
        private string[] plugins = {
@@ -55,11 +58,88 @@
        public MainControl(SldWorks swAddin)
        {
            var log = LogManager.GetLogger("Main");
            Logger = log;
            SwApp = swAddin;
            GlobalConfig = PluginSetting.Instance;
            InitializeComponent();
            self.DataContext = this;
            InitTcpServer();
            try
            {
                CheckAutoRunRegKey();
                StartListenerProcess();
            }
            catch (Exception e)
            {
                log.Error("Start Listener Error!", e);
            }
        }
        /// <summary>
        /// 设置监听器自启动
        /// </summary>
        private void CheckAutoRunRegKey()
        {
            RegistryKey root = null;
            RegistryKey key = null;
            try
            {
                root = Registry.CurrentUser;
                key = root.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);
                string name = "SolidWorksListener";
                if (key == null)
                {
                    key = root.CreateSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run");
                }
                // 没有路径或者路径指向exe不对,就更新自启动路径
                string listenerPath = key.GetValue(name)?.ToString();
                string rootDir = new DirectoryInfo(Assembly.GetExecutingAssembly().Location).Parent.FullName;
                string newPath = Path.Combine(rootDir, "Listener", "SolidWorksListener.exe");
                if (string.IsNullOrEmpty(listenerPath) || new Uri(listenerPath) != new Uri(newPath))
                {
                    key.SetValue(name, newPath, RegistryValueKind.String);
                }
            }
            catch (Exception e)
            {
                Logger.Error("CheckAutoRunRegKey Failed!", e);
            }
            finally
            {
                try
                {
                    if (key != null) key.Close();
                    if (root != null) root.Close();
                }
                catch (Exception ex)
                {
                    Logger.Error("Reg Key Close Failed!", ex);
                }
            }
        }
        /// <summary>
        /// 启动Listener相关进程
        /// </summary>
        public void StartListenerProcess()
        {
            string dir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            string path1 = Path.Combine(dir, "Listener", "SolidWorksListener.exe");
            if (File.Exists(path1))
            {
                ProcessStartInfo info = new ProcessStartInfo
                {
                    FileName = path1,
                    WorkingDirectory = Path.GetDirectoryName(path1)
                };
                new Process
                {
                    StartInfo = info
                }.Start();
            }
        }
        // 本地调试用,连接SolidWorks
PdmSwPlugin.PDM/PdmControl.xaml.cs
@@ -39,6 +39,7 @@
using System.Windows.Input;
using NPOI.POIFS.Properties;
using NPOI.POIFS.Crypt;
using System.Threading.Tasks.Schedulers;
namespace PdmSwPlugin.PDM
{
@@ -144,11 +145,11 @@
                    this.Warning("请打开一张图纸");
                    return new ObservableCollection<PdmBom>();
                }
                if (7 == doc.GetBlockingState())
                {
                    this.Warning("请等待文档加载完毕");
                    return new ObservableCollection<PdmBom>();
                }
                //if (7 == doc.GetBlockingState())
                //{
                //    this.Warning("请等待文档加载完毕");
                //    return new ObservableCollection<PdmBom>();
                //}
                DateTime beforeDT = DateTime.Now;
@@ -896,7 +897,7 @@
        public Dictionary<string, DrawInfo> GetAllProperties(List<string> ErrMsgs)
        {
            Dictionary<string, DrawInfo> result = new Dictionary<string, DrawInfo>();
            ConcurrentDictionary<string, DrawInfo> result = new ConcurrentDictionary<string, DrawInfo>();
            PdmBom topBom = model.BomTree[0];
            CountdownEvent counter = new CountdownEvent(1);
            _ = ThreadPool.QueueUserWorkItem(
@@ -906,7 +907,65 @@
                );
            counter.Wait();
            counter.Dispose();
            return result;
            return new Dictionary<string, DrawInfo>(result);
        }
        /// <summary>
        /// 获取全部属性
        /// </summary>
        /// <param name="param"></param>
        public void GetAll(object param)
        {
            object[] datas = param as object[];
            PdmBom bom = (PdmBom)datas[0];
            ModelDoc2 sldDoc = bom.doc;
            Component2 component = bom.component;
            ConcurrentDictionary<string, DrawInfo> result = (ConcurrentDictionary<string, DrawInfo>)datas[1];
            CountdownEvent counter = (CountdownEvent)datas[2];
            List<string> ErrMsgs = (List<string>)datas[3];
            int level = (int)datas[4];
            try
            {
                counter.TryAddCount();
                string filepath = bom.partNo;
                if (result.ContainsKey(filepath))
                {
                    return;
                }
                if (!bom.skipCheck)
                {
                    result[filepath] = GetSingleDrawInfo(bom);
                }
                ObservableCollection<PdmBom> children = bom.modules;
                if (children != null)
                {
                    foreach (PdmBom child in children)
                    {
                        _ = ThreadPool.QueueUserWorkItem(
                              new WaitCallback(GetAll),
                              new object[] { child, result, counter, ErrMsgs, 1 });
                    }
                }
                MaskAdorner.ShowMessage(content, filepath);
            }
            catch (Exception e)
            {
                bom.drawInfo.checkRuleResult = 2;
                bom.drawInfo.errMessages = new List<string> { e.Message };
                Logger.Error($"V{PdmUser.LoginUser.pluginVersion},[{bom.filePath}] Read MASS Properies Failed.", e);
            }
            finally
            {
                counter.Signal();
                if (level == 0)
                {
                    counter.Signal();
                }
            }
        }
        /// <summary>
@@ -926,6 +985,7 @@
            Dictionary<string, string> allProperties = new Dictionary<string, string>();
            allProperties["物料型号"] = bom.partModel;
            DrawInfo drawInfo = bom._drawInfo;
            drawInfo.isHidden = bom.isHidden;
            drawInfo.allProperties = allProperties;
            allProperties["压缩"] = bom.suppressed.ToString();
            allProperties["轻量化"] = bom.lightWeight.ToString();
@@ -947,7 +1007,7 @@
            // 工程图一致性检查
            allProperties["工程图是否存在"] = drawExists.ToString();
            allProperties["md5"] = bom.localD3Md5;
            if (bom.lost || sldDoc == null)
            if (bom.lost || bom.BomInfo.isHidden || sldDoc == null)
            {
                allProperties["图纸是否存在"] = "false";
                return drawInfo;
@@ -1005,17 +1065,28 @@
            return drawInfo;
        }
        /// <summary>
        /// 获取全部属性
        /// </summary>
        /// <param name="param"></param>
        public void GetAll(object param)
        public Dictionary<string, DrawInfo> GetAllPropertiesByTask(List<string> ErrMsgs)
        {
            ConcurrentDictionary<string, DrawInfo> result = new ConcurrentDictionary<string, DrawInfo>();
            PdmBom topBom = model.BomTree[0];
            CountdownEvent counter = new CountdownEvent(1);
            Task.Run(() =>
            {
                GetAllByTask(new object[] {
                topBom, result, counter, ErrMsgs, 0 });
            });
            counter.Wait();
            counter.Dispose();
            return new Dictionary<string, DrawInfo>(result);
        }
        public void GetAllByTask(object param)
        {
            object[] datas = param as object[];
            PdmBom bom = (PdmBom)datas[0];
            ModelDoc2 sldDoc = bom.doc;
            Component2 component = bom.component;
            Dictionary<string, DrawInfo> result = (Dictionary<string, DrawInfo>)datas[1];
            ConcurrentDictionary<string, DrawInfo> result = (ConcurrentDictionary<string, DrawInfo>)datas[1];
            CountdownEvent counter = (CountdownEvent)datas[2];
            List<string> ErrMsgs = (List<string>)datas[3];
            int level = (int)datas[4];
@@ -1023,24 +1094,34 @@
            {
                counter.TryAddCount();
                string filepath = bom.partNo;
                if (result.ContainsKey(filepath))
                lock (result)
                {
                    return;
                    if (result.ContainsKey(filepath))
                    {
                        if (bom.isHidden)
                        {
                            result[filepath].isHidden = true;
                        }
                        return;
                    }
                    if (!bom.skipCheck)
                    {
                        result[filepath] = GetSingleDrawInfo(bom);
                    }
                }
                if (!bom.skipCheck)
                {
                    result[filepath] = GetSingleDrawInfo(bom);
                }
                ObservableCollection<PdmBom> children = bom.modules;
                if (children != null)
                {
                    foreach (PdmBom child in children)
                    {
                        _ = ThreadPool.QueueUserWorkItem(
                              new WaitCallback(GetAll),
                              new object[] { child, result, counter, ErrMsgs, 1 });
                        Task.Run(() =>
                        {
                            GetAllByTask(new object[] { child, result, counter, ErrMsgs, 1 });
                        });
                    }
                }
                MaskAdorner.ShowMessage(content, filepath);
@@ -1054,7 +1135,10 @@
            finally
            {
                counter.Signal();
                if (level == 0) counter.Signal();
                if (level == 0)
                {
                    counter.Signal();
                }
            }
        }
@@ -1096,78 +1180,127 @@
            return allSuccess;
        }
        public void sb(dynamic[] datas) {
            /*Dictionary<string, DrawInfo> properties = datas[0];
            string key = datas[1];
            KeyValuePair<string, DrawInfo> property = datas[2];
            List<string> temp = datas[3];
            CountdownEvent counter = datas[4];
            try
            {
                int iii, ref bool allSuccess
                Logger.Info($"{key} checking rule...");
                iii++;
                Result<DrawInfo> result = Client.PostSyncAction<DrawInfo>(property.Value, "wpf/bom/openApi/checkRuleSingle");
                DrawInfo checkResult = result.HandleResult();
                properties[key].checkRuleResult = checkResult.checkRuleResult;
                properties[key].errMessages = checkResult.errMessages;
                var msgs = checkResult.errMessages;
                if (!properties[key].HistoryData && !checkResult.checkRuleOk)
                {
                    allSuccess = false;
                }
                if (!properties[key].HistoryData && msgs != null && msgs.Count > 0)
                {
                    lock (temp)
                    {
                        foreach (string msg in msgs)
                        {
                            temp.Add($"物料【{key}】未通过规则检查!{msg}");
                        }
                    }
                }
                MaskAdorner.ShowMessage(content, $"物料【{key}】检查完成");
            }
            catch (Exception ex)
            {
                properties[key].checkRuleResult = 2;
                properties[key].errMessages = new List<string> { "发起检查失败,请重试" };
                lock (temp)
                {
                    temp.Add($"物料【{key}】发起检查失败,请重试");
                }
                allSuccess = false;
                MaskAdorner.ShowMessage(content, $"物料【{key}】检查完成");
            }
            finally
            {
                counter.Signal();
            }*/
        }
        public bool DoCheckRuleAsync(out List<string> messages)
        {
            var temp = new List<string>();
            bool allSuccess = true;
            Dictionary<string, DrawInfo> properties = GetAllProperties(temp);
            Dictionary<string, DrawInfo> properties = GetAllPropertiesByTask(temp);
            MaskAdorner.ShowMessage(content, "正在请求数据...");
            var factory = LimitedConcurrencyLevelTaskScheduler.Factory;
           // var factory = LimitedConcurrencyLevelTaskScheduler.Factory;
            CountdownEvent counter = new CountdownEvent(properties.Count);
            int iii = 1;
            int iii = 0;
            foreach (KeyValuePair<string, DrawInfo> property in properties)
            {
                string key = property.Key;
                _ = ThreadPool.QueueUserWorkItem(
                (WaitCallback)delegate
                /// 这个方法最快,但不好管控,因为不知道属性字典有多大
                Task.Run(() =>
                {
                    string key = property.Key;
                    iii++;
                    try
                    {
                        Logger.Error($"{key} checking rule...");
                        iii++;
                        Result<DrawInfo> result = Client.PostSyncAction<DrawInfo>(property.Value, "wpf/bom/openApi/checkRuleSingle");
                        DrawInfo checkResult = result.HandleResult();
                        properties[key].checkRuleResult = checkResult.checkRuleResult;
                        properties[key].errMessages = checkResult.errMessages;
                        var msgs = checkResult.errMessages;
                        if (!properties[key].HistoryData && (!checkResult.checkRuleOk||property.Value.isHidden))
                        {
                            allSuccess = false;
                        }
                        if (!properties[key].HistoryData)
                        {
                            lock (temp)
                            {
                                if (property.Value.isHidden)
                                {
                                    temp.Add($"物料【{key}】被设置为隐藏!");
                                }
                                if (msgs != null && msgs.Count > 0)
                                {
                                    foreach (string msg in msgs)
                                    {
                                        temp.Add($"物料【{key}】未通过规则检查!{msg}");
                                    }
                                }
                            }
                        }
                        MaskAdorner.ShowMessage(content, $"物料【{key}】检查完成");
                    }
                    catch (Exception ex)
                    {
                        properties[key].checkRuleResult = 2;
                        properties[key].errMessages = new List<string> { "发起检查失败,请重试" };
                        lock (temp)
                        {
                            temp.Add($"物料【{key}】发起检查失败,请重试");
                        }
                        allSuccess = false;
                        MaskAdorner.ShowMessage(content, $"物料【{key}】检查完成");
                    }
                    finally
                    {
                        counter.Signal();
                    }
                });
                //LimitedConcurrencyLevelTaskScheduler scheduler = new LimitedConcurrencyLevelTaskScheduler(int.MaxValue);
                //Task.Factory.StartNew(() => {
                //    string key = property.Key;
                //    iii++;
                //    try
                //    {
                //        Logger.Error($"{key} checking rule...");
                //        Result<DrawInfo> result = Client.PostSyncAction<DrawInfo>(property.Value, "wpf/bom/openApi/checkRuleSingle");
                //        DrawInfo checkResult = result.HandleResult();
                //        properties[key].checkRuleResult = checkResult.checkRuleResult;
                //        properties[key].errMessages = checkResult.errMessages;
                //        var msgs = checkResult.errMessages;
                //        if (!properties[key].HistoryData && !checkResult.checkRuleOk)
                //        {
                //            allSuccess = false;
                //        }
                //        if (!properties[key].HistoryData && msgs != null && msgs.Count > 0)
                //        {
                //            lock (temp)
                //            {
                //                foreach (string msg in msgs)
                //                {
                //                    temp.Add($"物料【{key}】未通过规则检查!{msg}");
                //                }
                //            }
                //        }
                //        MaskAdorner.ShowMessage(content, $"物料【{key}】检查完成");
                //    }
                //    catch (Exception ex)
                //    {
                //        properties[key].checkRuleResult = 2;
                //        properties[key].errMessages = new List<string> { "发起检查失败,请重试" };
                //        lock (temp)
                //        {
                //            temp.Add($"物料【{key}】发起检查失败,请重试");
                //        }
                //        allSuccess = false;
                //        MaskAdorner.ShowMessage(content, $"物料【{key}】检查完成");
                //    }
                //    finally
                //    {
                //        counter.Signal();
                //    }
                //}, CancellationToken.None, TaskCreationOptions.None, scheduler);
                /// 下面两个都在管控Task数量,但还是很慢
                /*string key = property.Key;
                _ = ThreadPool.QueueUserWorkItem(
                (WaitCallback)delegate
                {
                    iii++;
                    try
                    {
                        Logger.Error($"{key} checking rule...");
                        Result<DrawInfo> result = Client.PostSyncAction<DrawInfo>(property.Value, "wpf/bom/openApi/checkRuleSingle");
                        DrawInfo checkResult = result.HandleResult();
                        properties[key].checkRuleResult = checkResult.checkRuleResult;
@@ -1205,12 +1338,53 @@
                    {
                        counter.Signal();
                    }
                });
                });*/
                /* factory.StartNew(() =>
                 {
                //factory.StartNew(() =>
                //{
                //    string key = property.Key;
                //    iii++;
                //    try
                //    {
                //        Logger.Error($"{key} checking rule...");
                //        Result<DrawInfo> result = Client.PostSyncAction<DrawInfo>(property.Value, "wpf/bom/openApi/checkRuleSingle");
                //        DrawInfo checkResult = result.HandleResult();
                //        properties[key].checkRuleResult = checkResult.checkRuleResult;
                //        properties[key].errMessages = checkResult.errMessages;
                //        var msgs = checkResult.errMessages;
                //        if (!properties[key].HistoryData && !checkResult.checkRuleOk)
                //        {
                //            allSuccess = false;
                //        }
                 });*/
                //        if (!properties[key].HistoryData && msgs != null && msgs.Count > 0)
                //        {
                //            lock (temp)
                //            {
                //                foreach (string msg in msgs)
                //                {
                //                    temp.Add($"物料【{key}】未通过规则检查!{msg}");
                //                }
                //            }
                //        }
                //        MaskAdorner.ShowMessage(content, $"物料【{key}】检查完成");
                //    }
                //    catch (Exception ex)
                //    {
                //        properties[key].checkRuleResult = 2;
                //        properties[key].errMessages = new List<string> { "发起检查失败,请重试" };
                //        lock (temp)
                //        {
                //            temp.Add($"物料【{key}】发起检查失败,请重试");
                //        }
                //        allSuccess = false;
                //        MaskAdorner.ShowMessage(content, $"物料【{key}】检查完成");
                //    }
                //    finally
                //    {
                //        counter.Signal();
                //    }
                //});
            }
            counter.Wait();
            counter.Dispose();
@@ -1245,7 +1419,7 @@
                try
                {
                    RefreshBomList(SwApp.IActiveDoc2);
                    if (!DoCheckRule(out List<string> msgs))
                    if (!DoCheckRuleAsync(out List<string> msgs))
                    {
                        Dispatcher.Invoke(() =>
                        {
@@ -1615,13 +1789,19 @@
                    return;
                }
                if (bom.checkRuleOk)
                if (bom.checkRuleOk && !bom.isHidden)
                {
                    this.Show("规则检查通过");
                }
                else
                {
                    MultiExWindow exWin = new MultiExWindow(this, "检查结果", bom.drawInfo.errMessages);
                    List<string> errs = new List<string>();
                    if (bom.isHidden)
                    {
                        errs.Add("文档被设置为隐藏");
                    }
                    errs.AddRange(bom.drawInfo.errMessages);
                    MultiExWindow exWin = new MultiExWindow(this, "检查结果", errs);
                    exWin.ShowDialog();
                }
            }
@@ -1817,7 +1997,7 @@
                        {
                            throw new CantCheckInException(new List<string> { "请打开一张图纸" });
                        }
                        DoCheckRule(out _);
                        DoCheckRuleAsync(out _);
                        // 筛选所有在物料明细表中,不跳过检查并且检查未通过的,类型是加工件的未通过审核的,加工件审核通过的但图纸变更的
                        List<string> errs = model.bomTreeReader.CacheList.Select(b => b.NeedStopCheckIn())
                        .Where(s => s != null).ToList();
PdmSwPlugin.PDM/PdmSwPlugin.PDM.csproj
@@ -98,6 +98,9 @@
    <Reference Include="NPOI.OpenXmlFormats, Version=2.6.0.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL">
      <HintPath>..\PdmSw\packages\NPOI.2.6.0\lib\net472\NPOI.OpenXmlFormats.dll</HintPath>
    </Reference>
    <Reference Include="ParallelExtensionsExtras, Version=1.2.0.0, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\packages\MSFT.ParallelExtensionsExtras.1.2.0\lib\ParallelExtensionsExtras.dll</HintPath>
    </Reference>
    <Reference Include="SixLabors.Fonts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d998eea7b14cab13, processorArchitecture=MSIL">
      <HintPath>..\PdmSw\packages\SixLabors.Fonts.1.0.0-beta19\lib\netstandard2.0\SixLabors.Fonts.dll</HintPath>
    </Reference>
PdmSwPlugin.PDM/packages.config
@@ -4,6 +4,7 @@
  <package id="MathNet.Numerics.Signed" version="4.15.0" targetFramework="net472" />
  <package id="Microsoft.Bcl.AsyncInterfaces" version="7.0.0" targetFramework="net472" />
  <package id="Microsoft.IO.RecyclableMemoryStream" version="2.2.0" targetFramework="net472" />
  <package id="MSFT.ParallelExtensionsExtras" version="1.2.0" targetFramework="net472" />
  <package id="Newtonsoft.Json" version="13.0.3" targetFramework="net472" />
  <package id="NPOI" version="2.6.0" targetFramework="net472" />
  <package id="Portable.BouncyCastle" version="1.9.0" targetFramework="net472" />
PdmSwPlugin.PropertySetting/CommonSettingControl.xaml.cs
@@ -53,8 +53,8 @@
        public const string size = "外形尺寸";
        public static readonly ObservableCollection<string> MaterialTypes = new ObservableCollection<string> { "普通件",
        "易损件","备件"
        };
       "机罩","机架","大板"
        };// "易损件","备件",
        public static readonly ObservableCollection<string> DocTypes = new ObservableCollection<string> { "模组", "加工件" };
        public static readonly HashSet<string> SpecialJgjType = new HashSet<string> { "型材件", "金属板焊接件" };
PdmSwPlugin.PropertySetting/Panel/Model/JgjBasePanelModel.cs
@@ -45,8 +45,8 @@
        }
        private ObservableCollection<string> _materialTypeItems = new ObservableCollection<string> { "普通件",
        "易损件","备件"
        };
       "机罩","机架","大板"
        };// "易损件","备件",
        public ObservableCollection<string> materialTypeItems
        {
            get => _materialTypeItems;
PdmSwPlugin.PropertySetting/PdmSwPlugin.PropertySetting.csproj
@@ -105,6 +105,9 @@
    </Reference>
  </ItemGroup>
  <ItemGroup>
    <Compile Include="SettingControl.xaml.cs">
      <DependentUpon>SettingControl.xaml</DependentUpon>
    </Compile>
    <Compile Include="CommonSettingControl.xaml.cs">
      <DependentUpon>CommonSettingControl.xaml</DependentUpon>
    </Compile>
@@ -133,6 +136,13 @@
    <Compile Include="PropertySettingControl.xaml.cs">
      <DependentUpon>PropertySettingControl.xaml</DependentUpon>
    </Compile>
    <Compile Include="Tab\JgjPartTab.xaml.cs">
      <DependentUpon>JgjPartTab.xaml</DependentUpon>
    </Compile>
    <Page Include="SettingControl.xaml">
      <Generator>MSBuild:Compile</Generator>
      <SubType>Designer</SubType>
    </Page>
    <Page Include="CommonSettingControl.xaml">
      <SubType>Designer</SubType>
      <Generator>MSBuild:Compile</Generator>
@@ -161,6 +171,10 @@
      <SubType>Designer</SubType>
      <Generator>MSBuild:Compile</Generator>
    </Page>
    <Page Include="Tab\JgjPartTab.xaml">
      <SubType>Designer</SubType>
      <Generator>MSBuild:Compile</Generator>
    </Page>
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Properties\AssemblyInfo.cs">
PdmSwPlugin.PropertySetting/SettingControl.xaml
New file
@@ -0,0 +1,39 @@
<UserControl x:Class="PdmSwPlugin.PropertySetting.SettingControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             mc:Ignorable="d"
             d:DesignHeight="450" d:DesignWidth="800">
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/PdmSwPlugin.Common;component/Style/ToolBar.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>
    <StackPanel>
        <ToolBarTray Background="#FFF" ToolBarTray.IsLocked="True" >
            <ToolBar Style="{StaticResource CommonToolBar}" ToolBar.OverflowMode="Never" Band="1" BandIndex="1" Height="30" Background="#FFF">
                <Button ToolTip="刷新" Content="&#xe631;刷新" Click="Refresh_Click" FontSize="16"/>
                <Button ToolTip="保存" Content="&#xe60d;保存" FontFamily="{StaticResource iconfont}" FontSize="16"
                        Click="SaveButton_Click"/>
                <!--<Button ToolTip="另存" Content="&#xe60b;" FontFamily="{StaticResource iconfont}" FontSize="16"
                        Click="SaveAsButton_Click"/>-->
                <!--<Button ToolTip="另存">
                    <Image Source="Image/save.png"/>
                </Button>-->
                <Button ToolTip="加载可选项" Content="&#xe752;加载可选项" Click="LoadComboBox_Click" FontSize="16"/>
            </ToolBar>
        </ToolBarTray>
        <Label Content="{Binding ReadDocPath}"/>
        <AdornerDecorator x:Name="content">
            <StackPanel x:Name="contentPanel">
            </StackPanel>
        </AdornerDecorator>
    </StackPanel>
</UserControl>
PdmSwPlugin.PropertySetting/SettingControl.xaml.cs
New file
@@ -0,0 +1,715 @@
using log4net;
using PdmSwPlugin.Commmon.Util.UI;
using PdmSwPlugin.Common.Util;
using PdmSwPlugin.Common.Util.Http;
using PdmSwPlugin.PropertySetting.Interface;
using SolidWorks.Interop.sldworks;
using SolidWorks.Interop.swconst;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using PdmSwPlugin.Common.Interface;
using PdmSwPlugin.Common;
using PdmSwPlugin.PropertySetting.Entity;
using PdmSwPlugin.PropertySetting.Panel;
using System.Windows.Threading;
using PdmSwPlugin.Common.Setting;
using System.IO;
using System.Runtime.InteropServices;
namespace PdmSwPlugin.PropertySetting
{
    /// <summary>
    /// CommonSettingControl.xaml 的交互逻辑
    /// </summary>
    [PdmSwPlugin(Title = "属性设置")]
    public partial class SettingControl : UserControl, ISwAppSetter, INotifyPropertyChanged
        , IActiveDocChangeHandler, ITabControlSelectionChangeHandler
    {
        private static ILog Logger = LogManager.GetLogger("PropertySetting");
        #region 不能公用的东西,真有你的啊C#
        public event PropertyChangedEventHandler PropertyChanged;
        public void RaisePropertyChanged(string name)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
        public void RaiseAndSetIfChanged<T>(ref T old, T @new, [CallerMemberName] string propertyName = null)
        {
            old = @new;
            if (propertyName != null)
            {
                RaisePropertyChanged(propertyName);
            }
        }
        #endregion
        public readonly Dictionary<string, UserControl> controlCache = new Dictionary<string, UserControl>();
        #region 属性
        public SldWorks SwApp { get; private set; }
        /// <summary>
        /// 激活的文档
        /// </summary>
        public ModelDoc2 activeDoc { set; get; }
        /// <summary>
        /// 上次读取的文档
        /// </summary>
        public ModelDoc2 LastReadDoc { get; set; }
        /// <summary>
        /// 当前读取的文档
        /// </summary>
        public ModelDoc2 ReadDoc { get; set; }
        /// <summary>
        /// 当前读取的组件
        /// </summary>
        public Component2 ReadComponent { get; set; }
        private HttpClient Client { get; set; }
        Dictionary<string, JgjType> settings;
        #endregion
        #region UI绑定
        private string _readDocPath;
        public string ReadDocPath
        {
            get => _readDocPath;
            set => RaiseAndSetIfChanged(ref _readDocPath, value);
        }
        #endregion
        private HttpClientCreator clientCreator { get; set; }
        private UserControl ActiveOpter { get; set; }
        public SettingControl()
        {
            clientCreator = new HttpClientCreator(new HttpConfig(PluginSetting.Instance.BaseAddress));
            InitializeComponent();
            DataContext = this;
        }
        public SettingControl(SldWorks SwApp) : this()
        {
            this.SwApp = SwApp;
        }
        public void InitPropertyData()
        {
            if (Client == null)
            {
                Client = clientCreator.GetClient();
            }
            DefaultPanel defaultPanel = new DefaultPanel();
            controlCache.Add("default", defaultPanel);
            JgjPartPanel jgjPart = new JgjPartPanel();
            controlCache.Add("jgjPart", jgjPart);
            JgjModulePanel jgjModule = new JgjModulePanel();
            controlCache.Add("jgjModule", jgjModule);
            var stPart = new StandardPartPanel();
            controlCache.Add("standardPart", stPart);
            var stModule = new StandardModulePanel();
            controlCache.Add("standardModule", stModule);
            LoadComboxItemSource();
            Refresh_Click(null, null);
        }
        private void Jgj_SinglePropertyChanged(object sender, string name, object value)
        {
            // CustomPropertyUtil.SetCustomProperties(ReadDoc, name, (string)value);
        }
        /// <summary>
        /// 从服务器加载各种选项
        /// </summary>
        private void LoadComboxItemSource()
        {
            try
            {
                Result<Dictionary<string, JgjType>> res = Client.GetSyncAction<Dictionary<string, JgjType>>("design/rule/openApi/test");
                Dictionary<string, JgjType> datas = res.HandleResult();
                settings = datas;
                foreach (var key in controlCache.Keys)
                {
                    (controlCache[key] as IPropertyOpt).SetSettings(settings);
                }
            }
            catch (Exception ex)
            {
                Logger.Error("Request Jgj properties failed.", ex);
                this.Error($"请求加工件属性失败!{ex.Message}");
            }
        }
        private void UpdateActiveDoc()
        {
            if (activeDoc != null)
            {
                DetachDocNotify(activeDoc);
            }
            activeDoc = SwApp.ActiveDoc;
            if (activeDoc != null)
            {
                AttachDocNotify(activeDoc);
                int docType = activeDoc.GetType();
                if (docType == (int)swDocumentTypes_e.swDocASSEMBLY)
                {
                    activeDoc.ClearSelection2(true);
                }
            }
            UpdateUI(activeDoc);
        }
        /// <summary>
        /// 附加一些插件范围内的事件
        /// </summary>
        /// <param name="doc"></param>
        private void AttachDocNotify(ModelDoc2 doc)
        {
            int docType = doc.GetType();
            if (docType == (int)swDocumentTypes_e.swDocASSEMBLY)
            {
                AssemblyDoc ass = doc as AssemblyDoc;
                ass.UserSelectionPostNotify += Ass_UserSelectionPostNotify;
                ass.DestroyNotify2 += ActiveDocDestroyNotify2;
            }
            else if (docType == (int)swDocumentTypes_e.swDocPART)
            {
                PartDoc part = doc as PartDoc;
                part.DestroyNotify2 += ActiveDocDestroyNotify2;
            }
            else if (docType == (int)swDocumentTypes_e.swDocDRAWING)
            {
                DrawingDoc draw = doc as DrawingDoc;
                draw.DestroyNotify2 += ActiveDocDestroyNotify2;
            }
        }
        /// <summary>
        /// 移除插件范围内的一些事件
        /// </summary>
        /// <param name="doc"></param>
        private void DetachDocNotify(ModelDoc2 doc)
        {
            try
            {
                int docType = doc.GetType();
                if (docType == (int)swDocumentTypes_e.swDocASSEMBLY)
                {
                    AssemblyDoc ass = doc as AssemblyDoc;
                    ass.UserSelectionPostNotify -= Ass_UserSelectionPostNotify;
                    ass.DestroyNotify2 -= ActiveDocDestroyNotify2;
                }
                else if (docType == (int)swDocumentTypes_e.swDocPART)
                {
                    PartDoc part = doc as PartDoc;
                    part.DestroyNotify2 -= ActiveDocDestroyNotify2;
                }
                else if (docType == (int)swDocumentTypes_e.swDocDRAWING)
                {
                    DrawingDoc draw = doc as DrawingDoc;
                    draw.DestroyNotify2 -= ActiveDocDestroyNotify2;
                }
            }
            catch (COMException e)
            {
                // 如果sw把不是装配体/零件体/工程图的文档关了,有时会报这个问题,留个日志不报错了
                Logger.Warn("COMObject detach event failed.", e);
                activeDoc = null;
            }
        }
        private int ActiveDocDestroyNotify2(int DestroyType)
        {
            if (activeDoc == null)
            {
                return 0;
            }
            DetachDocNotify(activeDoc);
            activeDoc = null;
            ReadComponent = null;
            UpdateUI(null);
            return 0;
        }
        public void UpdateUI(ModelDoc2 doc)
        {
            AlertSaveWindow();
            LastReadDoc = ReadDoc;
            ReadDoc = doc;
            Dispatcher.Invoke(() =>
            {
                SwitchVisiable();
                // LoadDocProperties();
            });
        }
        /// <summary>
        /// 判断是否需要弹窗提示保存
        /// </summary>
        public void AlertSaveWindow()
        {
            IPropertyOpt opt = ActiveOpter as IPropertyOpt;
            if (opt != null && opt.GetDocChanged())
            {
                // 历史文档直接重置
                string fullName = Path.GetFileName(ReadDocPath);
                if (NameUtil.IsHistoryDoc(fullName))
                {
                    opt.ResetProperty(out string errMsg);
                    return;
                }
                string Message = $"{fullName}属性发生变更,是否保存?";
                if (SwApp.SendMsgToUser2(Message, (int)swMessageBoxIcon_e.swMbWarning
                   , (int)swMessageBoxBtn_e.swMbYesNo) == (int)swMessageBoxResult_e.swMbHitYes)
                {
                    SaveDoc(true);
                }
                else
                {
                    opt.ResetProperty(out string errMsg);
                }
            }
        }
        private int Ass_UserSelectionPostNotify()
        {
            var swSelMgr = (SelectionMgr)activeDoc.SelectionManager;
            var i = swSelMgr.GetSelectedObjectCount2(-1);
            if (i > 0)
            {
                try
                {
                    Component2 component = swSelMgr.GetSelectedObjectsComponent4(1, -1);
                    ModelDoc2 doc = activeDoc;
                    ReadComponent = null;
                    if (component != null)
                    {
                        doc = component.IGetModelDoc();
                        ReadComponent = component;
                    }
                    UpdateUI(doc);
                }
                catch (Exception ex)
                {
                    Logger.Error("Ass Change Component Error.", ex);
                    this.Error($"刷新属性失败!{ex.Message}");
                }
            }
            return 1;
        }
        /// <summary>
        /// 根据激活的文档类型,变更属性可视
        /// </summary>
        private void SwitchVisiable()
        {
            HashSet<string> skipName = new HashSet<string> {
                NameConstant.materialCode
            };
            IPropertyOpt last = ActiveOpter as IPropertyOpt;
            string contentKey = "default";
            int? docType = ReadDoc?.GetType();
            UserControl control;
            IPropertyOpt newOne;
            Dictionary<string, string> properties;
            if (docType == (int)swDocumentTypes_e.swDocDRAWING)
            {
                ReadDocPath = ReadDoc.GetPathName();
                contentKey = "default";
                control = controlCache[contentKey];
                newOne = control as IPropertyOpt;
                newOne.SetProperties(null, "当前不支持工程图", true, out _);
            }
            else if (docType == (int)swDocumentTypes_e.swDocPART)
            {
                ReadDocPath = ReadDoc.GetPathName();
                properties = CustomPropertyUtil.GetCustomProperties2(ReadDoc, true, skipName);
                string fileType = properties.Get(NameConstant.docType);
                /*if (fileType == "加工件" || fileType == "模组")
                {
                    contentKey = "jgjPart";
                }*/
                if (BomIniterHolder.Instance.IsJgj(ReadDoc))
                {
                    contentKey = "jgjPart";
                }
                else
                {
                    contentKey = "standardPart";
                }
                control = controlCache[contentKey];
                newOne = control as IPropertyOpt;
                newOne.SetProperties(ReadDoc, properties, true, out _);
            }
            else if (docType == (int)swDocumentTypes_e.swDocASSEMBLY)
            {
                ReadDocPath = ReadDoc.GetPathName();
                if (ReadDoc.IsOpenedViewOnly())
                {
                    contentKey = "default";
                    control = controlCache[contentKey];
                    newOne = control as IPropertyOpt;
                    newOne.SetProperties(null, "当前处于只读模式", true, out _);
                }
                else if (ReadDoc.IsOpenedReadOnly())
                {
                    contentKey = "default";
                    control = controlCache[contentKey];
                    newOne = control as IPropertyOpt;
                    newOne.SetProperties(null, "当前处于只读模式", true, out _);
                }
                else
                {
                    // !Equals(LastReadDoc, ReadDoc)
                    properties = CustomPropertyUtil.GetCustomProperties2(ReadDoc, true, skipName);
                    string fileType = properties.Get(NameConstant.docType);
                    /*if (fileType == "加工件" || fileType == "模组")
                    {
                        contentKey = "jgjPart";
                    }*/
                    if (BomIniterHolder.Instance.IsJgj(ReadDoc))
                    {
                        contentKey = "jgjModule";
                    }
                    else
                    {
                        contentKey = "standardModule";
                    }
                    control = controlCache[contentKey];
                    newOne = control as IPropertyOpt;
                    newOne.SetProperties(ReadDoc, properties, true, out _);
                }
            }
            else
            {
                contentKey = "default";
                control = controlCache[contentKey];
                newOne = control as IPropertyOpt;
                string PathName = ReadComponent?.GetPathName();
                if (PathName == null)
                {
                    ReadDocPath = "";
                    newOne.SetProperties(ReadDoc, "请打开一个文档", true, out _);
                }
                else
                {
                    ReadDocPath = PathName;
                    string name = Path.GetFileNameWithoutExtension(PathName);
                    newOne.SetProperties(ReadDoc, $"【{name}】未找到文档,请检查是否被压缩或轻量化", true, out _);
                }
            }
            if (last != null)
            {
                last.UpdateProperty -= Jgj_SinglePropertyChanged;
                last = null;
            }
            ActiveOpter = control;
            contentPanel.Children.Clear();
            newOne.UpdateProperty += Jgj_SinglePropertyChanged;
            contentPanel.Children.Add(control);
        }
        /// <summary>
        /// 根据激活的文档类型,变更属性可视
        /// </summary>
        private void SwitchVisiable2()
        {
            HashSet<string> skipName = new HashSet<string> {
                NameConstant.materialCode
            };
            IPropertyOpt last = ActiveOpter as IPropertyOpt;
            string contentKey = "default";
            int? docType = ReadDoc?.GetType();
            UserControl control;
            IPropertyOpt newOne;
            Dictionary<string, string> properties;
            if (docType == (int)swDocumentTypes_e.swDocDRAWING)
            {
                ReadDocPath = ReadDoc.GetPathName();
                control = new DefaultPanel();
                newOne = control as IPropertyOpt;
                newOne.SetSettings(settings);
                newOne.SetProperties(null, "当前不支持工程图", true, out _);
            }
            else if (docType == (int)swDocumentTypes_e.swDocPART)
            {
                ReadDocPath = ReadDoc.GetPathName();
                properties = CustomPropertyUtil.GetCustomProperties2(ReadDoc, true, skipName);
                string fileType = properties.Get(NameConstant.docType);
                /*if (fileType == "加工件" || fileType == "模组")
                {
                    contentKey = "jgjPart";
                }*/
                if (BomIniterHolder.Instance.IsJgj(ReadDoc))
                {
                    control = new JgjPartPanel();
                }
                else
                {
                    control = new StandardPartPanel();
                }
                newOne = control as IPropertyOpt;
                newOne.SetSettings(settings);
                newOne.SetProperties(ReadDoc, properties, true, out _);
            }
            else if (docType == (int)swDocumentTypes_e.swDocASSEMBLY)
            {
                ReadDocPath = ReadDoc.GetPathName();
                // !Equals(LastReadDoc, ReadDoc)
                properties = CustomPropertyUtil.GetCustomProperties2(ReadDoc, true, skipName);
                string fileType = properties.Get(NameConstant.docType);
                /*if (fileType == "加工件" || fileType == "模组")
                {
                    contentKey = "jgjPart";
                }*/
                if (BomIniterHolder.Instance.IsJgj(ReadDoc))
                {
                    control = new JgjModulePanel();
                }
                else
                {
                    control = new StandardModulePanel();
                }
                newOne = control as IPropertyOpt;
                newOne.SetSettings(settings);
                newOne.SetProperties(ReadDoc, properties, true, out _);
            }
            else
            {
                control = new DefaultPanel();
                newOne = control as IPropertyOpt;
                string PathName = ReadComponent?.GetPathName();
                if (PathName == null)
                {
                    ReadDocPath = "";
                    newOne.SetSettings(settings);
                    newOne.SetProperties(ReadDoc, "请打开一个文档", true, out _);
                }
                else
                {
                    ReadDocPath = PathName;
                    string name = Path.GetFileNameWithoutExtension(PathName);
                    newOne.SetSettings(settings);
                    newOne.SetProperties(ReadDoc, $"【{name}】未找到文档,请检查是否被压缩或轻量化", true, out _);
                }
            }
            if (last != null)
            {
                last.UpdateProperty -= Jgj_SinglePropertyChanged;
                last = null;
            }
            ActiveOpter = control;
            contentPanel.Children.Clear();
            newOne.UpdateProperty += Jgj_SinglePropertyChanged;
            contentPanel.Children.Add(control);
        }
        /// <summary>
        /// 从激活的文档中读取参数
        /// </summary>
        private void LoadDocProperties()
        {
            IPropertyOpt opt = ActiveOpter as IPropertyOpt;
            string ErrMsg = null;
            if (ReadDoc == null)
            {
                string PathName = ReadComponent?.GetPathName();
                if (PathName == null)
                {
                    ReadDocPath = "";
                    opt.SetProperties(ReadDoc, "请打开一个文档", true, out ErrMsg);
                    return;
                }
                ReadDocPath = PathName;
                string name = Path.GetFileNameWithoutExtension(PathName);
                opt.SetProperties(ReadDoc, $"【{name}】未找到文档,请检查是否被压缩或轻量化", true, out ErrMsg);
                return;
            }
            int docType = ReadDoc.GetType();
            ReadDocPath = ReadDoc.GetPathName();
            if (docType == (int)swDocumentTypes_e.swDocDRAWING)
            {
                opt.SetProperties(null, "当前不支持工程图", true, out ErrMsg);
                return;
            }
            HashSet<string> skipName = new HashSet<string> {
                NameConstant.materialCode
            };
            Dictionary<string, string> properties = CustomPropertyUtil.GetCustomProperties2(ReadDoc, true, skipName);
            opt.SetProperties(ReadDoc, properties, !Equals(LastReadDoc, ReadDoc), out ErrMsg);
        }
        private void ClearDocProperties()
        {
            IPropertyOpt opt = ActiveOpter as IPropertyOpt;
            opt.ClearAllProperties(out string ErrMsg);
        }
        /// <summary>
        /// 将属性设置进文档,注意,并没有保存
        /// </summary>
        /// <param name="doc">文档</param>
        private void SetDocProperty(ModelDoc2 doc, Dictionary<string, string> props)
        {
            CustomPropertyUtil.SetCustomProperties(doc, props);
        }
        public void SetSwApp(SldWorks SwApp)
        {
            this.SwApp = SwApp;
        }
        private void SaveDoc(bool qiaoqiaode)
        {
            int errors = 0, warnings = 0;
            if ((ActiveOpter as IPropertyOpt).SaveDoc(ref errors, ref warnings))
            {
                // if (!qiaoqiaode) this.Info("保存成功");
            }
        }
        private void SaveButton_Click(object sender, RoutedEventArgs e)
        {
            if (ReadDoc == null)
            {
                return;
            }
            SaveDoc(false);
        }
        public void RefreshData()
        {
            MaskAdorner.ShowMask(content, "属性加载中,请稍候...");
            Task.Run(() =>
            {
                try
                {
                    UpdateActiveDoc();
                }
                catch (COMException come)
                {
                    // 频繁关闭会抛出这个异常,不管了
                    Logger.Warn("Read property COMObject failed.", come);
                }
                catch (Exception ex)
                {
                    Logger.Error($"读取参数异常,文件:[{ReadDocPath}]!", ex);
                    this.Error($"读取参数异常:{ex.Message}");
                }
                finally
                {
                    MaskAdorner.HideMask(content);
                }
            });
        }
        private void Refresh_Click(object sender, RoutedEventArgs e)
        {
            RefreshData();
        }
        private void LoadComboBox_Click(object sender, RoutedEventArgs e)
        {
            MaskAdorner.ShowMask(content, "加载MES设置,请稍候...");
            Task.Run(() =>
            {
                try
                {
                    LoadComboxItemSource();
                }
                finally
                {
                    MaskAdorner.HideMask(content);
                }
            });
        }
        private void PropertySettingControl_Initialized(object sender, EventArgs e)
        {
            InitPropertyData();
        }
        /// <summary>
        /// 激活的文档变更触发
        /// </summary>
        /// <param name="lastDoc"></param>
        /// <param name="doc"></param>
        /// <param name="comp"></param>
        public void OnSwActiveDocChange(ModelDoc2 lastDoc, ModelDoc2 doc, Component2 comp)
        {
            // CurrentChanged();
            RefreshData();
        }
        public void OnSwActiveDocSaved(ModelDoc2 doc, Component2 comp)
        {
            // 读取文件,设置参数
            // LoadDocProperties();
        }
        public void OnCustomPropertyChange(string propName, string Configuration, string oldValue, string NewValue, int valueType)
        {
            if (oldValue == NewValue)
            {
                return;
            }
            IPropertyOpt opt = ActiveOpter as IPropertyOpt;
            opt.UpdateSingleProperty(propName, NewValue);
        }
        public void OnDocDestroy(ModelDoc2 doc)
        {
        }
        public void AfterDocDestroy()
        {
        }
        public void OnTabControlSelectionChange(object sender, SelectionChangedEventArgs e)
        {
            if (e.RemovedItems == null)
            {
                return;
            }
            foreach (object obj in e.RemovedItems)
            {
                if (obj is TabItem item)
                {
                    if (item.Content == this)
                    {
                        AlertSaveWindow();
                        break;
                    }
                }
                else
                {
                    return;
                }
            }
        }
    }
}
PdmSwPlugin.PropertySetting/Tab/JgjPartTab.xaml
New file
@@ -0,0 +1,88 @@
<UserControl x:Class="PdmSwPlugin.PropertySetting.Tab.JgjPartTab"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:PdmSwPlugin.PropertySetting.Tab"
             mc:Ignorable="d"
             x:Name="self" d:DesignHeight="900" d:DesignWidth="800" Background="#FFF">
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/PdmSwPlugin.Common;component/Style/ToolBar.xaml"/>
                <ResourceDictionary Source="/PdmSwPlugin.Common;component/Style/ComboxStyle.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>
    <StackPanel>
        <StackPanel x:Name="materialCodePanel">
            <Label Content="物料编码"/>
            <TextBox x:Name="materialCodeText" IsReadOnly="True" Text="{Binding materialCode,UpdateSourceTrigger=PropertyChanged}"/>
        </StackPanel>
        <StackPanel x:Name="weightPanel">
            <Label Content="重量(kg)"/>
            <TextBox IsReadOnly="True" x:Name="weightText" Text="{Binding weight}"/>
        </StackPanel>
        <StackPanel x:Name="materialNamePanel">
            <Label Content="物料名称"/>
            <TextBox x:Name="materialNameText" Text="{Binding materialName,UpdateSourceTrigger=PropertyChanged}"/>
        </StackPanel>
        <StackPanel x:Name="jgjTypePanel">
            <Label Content="加工件类型"/>
            <ComboBox x:Name="jgjTypeInput" Style="{StaticResource ShowTextCombox}"
                      Text="{Binding jgjType,Mode=TwoWay}"
                      ItemsSource="{Binding jgjTypeItems}" />
        </StackPanel>
        <StackPanel x:Name="stuffPanel">
            <Label Content="材质"/>
            <ComboBox x:Name="stuffInput" Style="{StaticResource ShowTextCombox}"
                      Text="{Binding stuff,Mode=TwoWay}"
                      ItemsSource="{Binding stuffItems}"
                      DropDownOpened="stuffInput_DropDownOpened"/>
        </StackPanel>
        <StackPanel x:Name="surfacePanel">
            <Label Content="表面处理"/>
            <ComboBox x:Name="surfaceInput" Style="{StaticResource ShowTextCombox}"
                        Text="{Binding surface,Mode=TwoWay}"
                        ItemsSource="{Binding surfaceItems}" DropDownOpened="stuffInput_DropDownOpened"/>
        </StackPanel>
        <StackPanel x:Name="heatPanel">
            <Label Content="热处理"/>
            <ComboBox x:Name="heatInput" Style="{StaticResource ShowTextCombox}"
                        Text="{Binding heat,Mode=TwoWay}"
                        ItemsSource="{Binding heatItems}" DropDownOpened="stuffInput_DropDownOpened"/>
        </StackPanel>
        <StackPanel x:Name="materialTypePanel">
            <Label Content="物料类型"/>
            <ComboBox ItemsSource="{Binding materialTypeItems}" SelectedItem="{Binding materialType,Mode=TwoWay}"/>
        </StackPanel>
        <StackPanel x:Name="createUserPanel">
            <Label Content="设计人员"/>
            <TextBox x:Name="createUserText" Text="{Binding designer,UpdateSourceTrigger=PropertyChanged}"/>
        </StackPanel>
        <StackPanel x:Name="remarkPanel">
            <Label Content="备注"/>
            <TextBox x:Name="remarkText" Text="{Binding remark,UpdateSourceTrigger=PropertyChanged}" />
        </StackPanel>
        <StackPanel x:Name="formatPanel">
            <Label Content="文件格式"/>
            <ComboBox ItemsSource="{Binding docTypeItems}" IsEnabled="{Binding DocTypeEnabled}"
SelectedItem="{Binding docType,Mode=TwoWay}"/>
        </StackPanel>
        <StackPanel x:Name="versionChangePanel">
            <CheckBox Content="版本变更" IsChecked="{Binding versionChangeBind}"/>
        </StackPanel>
    </StackPanel>
</UserControl>
PdmSwPlugin.PropertySetting/Tab/JgjPartTab.xaml.cs
New file
@@ -0,0 +1,473 @@
using PdmSwPlugin.Common.CustomHandler;
using PdmSwPlugin.Common.Util;
using PdmSwPlugin.PropertySetting.Entity;
using PdmSwPlugin.PropertySetting.Interface;
using PdmSwPlugin.PropertySetting.Panel.Attr;
using SolidWorks.Interop.sldworks;
using SolidWorks.Interop.swconst;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Runtime.CompilerServices;
using System.Windows.Controls;
namespace PdmSwPlugin.PropertySetting.Tab
{
    /// <summary>
    /// JgjPartTab.xaml 的交互逻辑
    /// </summary>
    public partial class JgjPartTab : UserControl, INotifyPropertyChanged, IPropertyOpt
    {
        #region 不能公用的东西,真有你的啊C#
        public event PropertyChangedEventHandler PropertyChanged;
        public void RaisePropertyChanged(string name)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
        public void RaiseAndSetIfChanged<T>(ref T old, T @new, [CallerMemberName] string propertyName = null)
        {
            old = @new;
            if (propertyName != null)
            {
                RaisePropertyChanged(propertyName);
                /*var attr = this.GetType().GetProperty(propertyName)?.GetCustomAttribute<PropertySettingAttr>();
                if (attr == null)
                {
                    return;
                }
                if (attr.NeedSave)
                {
                    UpdateProperty?.Invoke(this, attr.Name, @new);
                }*/
            }
        }
        #endregion
        public void ccc<T>(ref T old, T @new, [CallerMemberName] string propertyName = null)
        {
            old = @new;
            if (propertyName != null)
            {
                RaisePropertyChanged(propertyName);
            }
        }
        public event PanelPropertyChanged UpdateProperty;
        /// <summary>
        /// 初始数据
        /// </summary>
        private Dictionary<string, string> InitData = new Dictionary<string, string>();
        /// <summary>
        /// 实际数据
        /// </summary>
        private Dictionary<string, string> SaveData = new Dictionary<string, string>();
        private Dictionary<string, JgjType> datas;
        private Dictionary<string, ObservableCollection<string>> stuffItemCache;
        private Dictionary<string, ObservableCollection<string>> surfaceItemCache;
        private Dictionary<string, ObservableCollection<string>> heatItemCache;
        private ModelDoc2 doc;
        #region 下拉框数据源
        private ObservableCollection<string> _jgjTypeItems;
        public ObservableCollection<string> jgjTypeItems
        {
            get => _jgjTypeItems;
            set => RaiseAndSetIfChanged(ref _jgjTypeItems, value);
        }
        private ObservableCollection<string> _stuffItems;
        public ObservableCollection<string> stuffItems
        {
            get => _stuffItems;
            set => RaiseAndSetIfChanged(ref _stuffItems, value);
        }
        private ObservableCollection<string> _surfaceItems;
        public ObservableCollection<string> surfaceItems
        {
            get => _surfaceItems;
            set => RaiseAndSetIfChanged(ref _surfaceItems, value);
        }
        private ObservableCollection<string> _heatItems;
        public ObservableCollection<string> heatItems
        {
            get => _heatItems;
            set => RaiseAndSetIfChanged(ref _heatItems, value);
        }
        private ObservableCollection<string> _materialTypeItems = NameConstant.MaterialTypes;
        public ObservableCollection<string> materialTypeItems
        {
            get => _materialTypeItems;
            set => RaiseAndSetIfChanged(ref _materialTypeItems, value);
        }
        private ObservableCollection<string> _docTypeItems = NameConstant.DocTypes;
        public ObservableCollection<string> docTypeItems
        {
            get => _docTypeItems;
            set => RaiseAndSetIfChanged(ref _docTypeItems, value);
        }
        #endregion
        private bool _docTypeEnabled = true;
        [PropertySettingAttr(NeedInit = false, NeedSave = false)]
        public bool DocTypeEnabled
        {
            get => _docTypeEnabled;
            set => RaiseAndSetIfChanged(ref _docTypeEnabled, value);
        }
        #region UI属性
        private string _materialCode;
        [PropertySettingAttr(Name = NameConstant.materialCode, defaultValue = "$PRP:\"SW-File Name\"")]
        public string materialCode
        {
            get => _materialCode;
            set
            {
                RaiseAndSetIfChanged(ref _materialCode, value);
            }
        }
        private string _materialName;
        [PropertySettingAttr(Name = NameConstant.materialName)]
        public string materialName
        {
            get => _materialName;
            set
            {
                RaiseAndSetIfChanged(ref _materialName, value);
            }
        }
        private string _jgjType;
        [PropertySettingAttr(Name = NameConstant.jgjType)]
        public string jgjType
        {
            get => _jgjType;
            set
            {
                string temp = value;// jgjTypeItems.Contains(value) ? value : "无";
                var datas = stuffItemCache.Get(temp, new ObservableCollection<string> { "无" });
                RaiseAndSetIfChanged(ref _stuffItems, datas, "stuffItems");
                RaiseAndSetIfChanged(ref _jgjType, temp);
                UpdateField("jgjType", temp);
            }
        }
        private string _stuff;
        [PropertySettingAttr(Name = NameConstant.stuff)]
        public string stuff
        {
            get => _stuff;
            set
            {
                string temp = value;// stuffItems.Contains(value) ? value : "无";
                var sDatas = surfaceItemCache.Get($"{jgjType}_{temp}", new ObservableCollection<string> { "无" });
                var hDatas = heatItemCache.Get($"{jgjType}_{temp}", new ObservableCollection<string> { "无" });
                ccc(ref _surfaceItems, sDatas, "surfaceItems");
                ccc(ref _heatItems, hDatas, "heatItems");
                ccc(ref _stuff, temp);
            }
        }
        private string _surface;
        [PropertySettingAttr(Name = NameConstant.surface)]
        public string surface
        {
            get => _surface;
            set
            {
                string temp = value;// surfaceItems.Contains(value) ? value : "无";
                ccc(ref _surface, temp);
            }
        }
        private string _heat;
        [PropertySettingAttr(Name = NameConstant.heat)]
        public string heat
        {
            get => _heat;
            set
            {
                string temp = value;// heatItems.Contains(value) ? value : "无";
                ccc(ref _heat, temp);
            }
        }
        private string _weight = "";
        [PropertySettingAttr(Name = NameConstant.weight, NeedSave = false)]
        public string weight
        {
            get => CustomPropertyUtil.GetMass(doc);
            set
            {
                ccc(ref _weight, value);
            }
        }
        [PropertySettingAttr(Name = NameConstant.weight, NeedInit = false)]
        public string weightEval
        {
            get => doc == null ? null : $"\"SW-质量@{Path.GetFileName(doc.GetPathName())}\"";
            set { }
        }
        private string _materialType = "";
        [PropertySettingAttr(Name = NameConstant.materialType, defaultValue = "普通件")]
        public string materialType
        {
            get => _materialType;
            set
            {
                RaiseAndSetIfChanged(ref _materialType, value);
            }
        }
        private string _designer = "";
        [PropertySettingAttr(Name = NameConstant.designer)]
        public string designer
        {
            get => _designer;
            set
            {
                RaiseAndSetIfChanged(ref _designer, value);
            }
        }
        private string _remark = "";
        [PropertySettingAttr(Name = NameConstant.remark)]
        public string remark
        {
            get => _remark;
            set
            {
                RaiseAndSetIfChanged(ref _remark, value);
            }
        }
        private string _docType = "";
        [PropertySettingAttr(Name = NameConstant.docType, defaultValue = "加工件")]
        public string docType
        {
            get => _docType;
            set
            {
                string temp = value;
                if (NameConstant.SpecialJgjType.Contains(jgjType))
                {
                    temp = "加工件";
                }
                ccc(ref _docType, temp);
            }
        }
        private string _versionChange = "0";
        [PropertySettingAttr(Name = NameConstant.versionChange, defaultValue = "0")]
        public string versionChange
        {
            get => _versionChange;
            set
            {
                RaiseAndSetIfChanged(ref _versionChange, value);
                RaiseAndSetIfChanged(ref _versionChangeBind, value == "1", "versionChangeBind");
            }
        }
        private bool _versionChangeBind = false;
        [PropertySettingAttr(Name = NameConstant.versionChange, NeedSave = false, NeedInit = false)]
        public bool versionChangeBind
        {
            get => _versionChangeBind;
            set
            {
                RaiseAndSetIfChanged(ref _versionChangeBind, value);
                RaiseAndSetIfChanged(ref _versionChange, value ? "1" : "0", "versionChange");
            }
        }
        #endregion
        public JgjPartTab()
        {
            InitializeComponent();
            DataContext = this;
        }
        /// <summary>
        /// 设置属性
        /// </summary>
        /// <param name="properties"></param>
        /// <param name="errMsg"></param>
        /// <returns></returns>
        public bool SetProperties(ModelDoc2 doc, object properties, bool docChange, out string errMsg)
        {
            this.doc = doc;
            var data = docChange ? InitData : null;
            return NameConstant.SetProperties(this, properties, data, out errMsg);
        }
        public bool SaveDoc(ref int err, ref int warn)
        {
            Dictionary<string, string> props = GetAllProperties();
            CustomPropertyUtil.SetCustomProperties(doc, props);
            if (doc.Save3((int)swSaveAsOptions_e.swSaveAsOptions_AvoidRebuildOnSave,
                    ref err, ref warn))
            {
                InitData = props;
                return true;
            }
            return false;
        }
        /// <summary>
        /// 获取属性
        /// </summary>
        /// <returns></returns>
        public Dictionary<string, string> GetAllProperties()
        {
            return NameConstant.GetAllProperties(this);
        }
        public bool UpdateSingleProperty(string name, string value)
        {
            return NameConstant.UpdateSingleProperty(this, name, value);
        }
        public void RefreshItem()
        {
            if (datas == null)
            {
                return;
            }
            var finalStuffs = stuffItemCache.Get(jgjType, new ObservableCollection<string> { "无" });
            string key = $"{jgjType}_{stuff}";
            var finalSurfaces = surfaceItemCache.Get(key, new ObservableCollection<string> { "无" });
            var finalHeats = heatItemCache.Get(key, new ObservableCollection<string> { "无" });
            Dispatcher.Invoke(() =>
            {
                stuffItems = finalStuffs;
                surfaceItems = finalSurfaces;
                heatItems = finalHeats;
            });
        }
        public bool SetSettings(object settings)
        {
            Dictionary<string, JgjType> datas = settings as Dictionary<string, JgjType>;
            this.datas = datas;
            stuffItemCache = new Dictionary<string, ObservableCollection<string>>();
            surfaceItemCache = new Dictionary<string, ObservableCollection<string>>();
            heatItemCache = new Dictionary<string, ObservableCollection<string>>();
            ObservableCollection<string> jgjTypes = new ObservableCollection<string> { "无" };
            foreach (string key in datas.Keys)
            {
                jgjTypes.Add(key);
                JgjType type = datas[key];
                ObservableCollection<string> stuffs = new ObservableCollection<string> { "无" };
                Dictionary<string, StuffType> stuffDatas = type.stuffMap;
                foreach (string stuff in stuffDatas.Keys)
                {
                    if (stuff != "无")
                    {
                        stuffs.Add(stuff);
                    }
                    StuffType stuffType = stuffDatas[stuff];
                    string key2 = key + "_" + stuff;
                    ObservableCollection<string> surfaces = new ObservableCollection<string> { "无" };
                    ObservableCollection<string> heats = new ObservableCollection<string> { "无" };
                    foreach (string surface in stuffType.surfaceParam)
                    {
                        if (surface != "无") surfaces.Add(surface);
                    }
                    foreach (string heat in stuffType.heatParam)
                    {
                        if (heat != "无") heats.Add(heat);
                    }
                    surfaceItemCache.Add(key2, surfaces);
                    heatItemCache.Add(key2, heats);
                }
                stuffItemCache.Add(key, stuffs);
                if (!stuffItemCache.ContainsKey("无"))
                {
                    stuffItemCache.Add("无", new ObservableCollection<string> { "无" });
                }
            }
            Dispatcher.Invoke(() =>
            {
                jgjTypeItems = jgjTypes;
            });
            return true;
        }
        public bool ClearAllProperties(out string ErrMsg)
        {
            ErrMsg = null;
            return true;
        }
        public bool GetDocChanged()
        {
            return NameConstant.CompareWithInit(this, InitData);
        }
        public bool ResetProperty(out string errMsg)
        {
            return SetProperties(doc, InitData, false, out errMsg);
        }
        private void stuffInput_DropDownOpened(object sender, System.EventArgs e)
        {
            ComboBox comboBox = sender as ComboBox;
            if (comboBox == null) return;
            if (comboBox.Name == "stuffInput")
            {
                stuffItems = stuffItemCache.Get(jgjType, new ObservableCollection<string> { "无" });
            }
            else if (comboBox.Name == "surfaceInput")
            {
                string key = $"{jgjType}_{stuff}";
                surfaceItems = surfaceItemCache.Get(key, new ObservableCollection<string> { "无" });
            }
            else if (comboBox.Name == "heatInput")
            {
                string key = $"{jgjType}_{stuff}";
                heatItems = heatItemCache.Get(key, new ObservableCollection<string> { "无" });
            }
        }
        private void UpdateField(string field, string value)
        {
            if (field == "jgjType")
            {
                if (NameConstant.SpecialJgjType.Contains(value))
                {
                    docType = "加工件";
                    DocTypeEnabled = false;
                }
                else
                {
                    DocTypeEnabled = true;
                }
                return;
            }
        }
    }
}
SolidWorksListener/Listener.cs
@@ -6,6 +6,7 @@
using System.Net;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Text;
using System.Timers;
using System.Windows;
@@ -84,7 +85,7 @@
            // WinAPI_Interop.ShowServiceMessage(msg, "提示");
            // ShowMessageBox(msg, "提示");
            string exeDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            string alertPath = Path.GetFullPath(Path.Combine(exeDir,"..","Alert.exe"));
            string alertPath = Path.GetFullPath(Path.Combine(exeDir, "..", "Alert.exe"));
            if (File.Exists(alertPath))
            {
                Process.Start(alertPath);
@@ -221,9 +222,16 @@
        private bool IsSwRunning()
        {
            Process[] ps = Process.GetProcessesByName("SLDWORKS");
            bool IsRunning = (ps != null && ps.Length > 0);
            bool IsRunning = false;
            if (ps == null || ps.Length <= 0)
            {
                log.Debug($"Sw Is Running: {IsRunning}");
                return false;
            }
            IsRunning = true;
            string username = WindowsIdentity.GetCurrent().Name;
            log.Debug($"Sw Is Running: {IsRunning}");
            return IsRunning;
            return false;
        }
        /// <summary>
@@ -232,7 +240,7 @@
        private void HandleErr()
        {
            log.Debug($"err_count: {err_count}");
            if (++err_count > 3)
            if (++err_count > 5)
            {
                if (IsSwRunning())
                {
WpfUI/AsyncAttacher.cs
@@ -22,7 +22,7 @@
            
            while (modDoc != null)
            {
                LimitedConcurrencyLevelTaskScheduler.Factory.StartNew(() => {
                Task.Factory.StartNew(() => {
                    if (!OpenDocContext.IsOpenDoc(modDoc))
                    {
                        AttachModelDocEventHandler(modDoc);