• mis导入器的加强版——vdproj文件资源浏览器


      上次做的那个导入器不够强大,限制还不小,用起来不方便。于是就再做一个这样的工具。代码基本上不同了,思想还是差不多,但功能肯定比之前的强大。经过了这次编写工具,对vdporj文件的了解又深一层了。

    在vs的文件系统编辑器使用过程中,发现有两个不方便:第一是删除文件夹不方便,如果一个文件夹不是空的话,是删不成功的;第二是添加文件夹时,只能添加该文件夹的文件,如果指定的文件夹含有子文件夹,那些子文件夹就要手动一个个去添加,不会一同添加进去。

      针对第二个问题,我就写出了之前的那个导入器,针对第一个问题,我就写了这个浏览器。这回就先看一下界面

     

    功能大致有一下几个

             同步文件夹:把“应用程序文件夹”里的某个文件夹与磁盘上的某个文件夹同步,使得与磁盘上的文件夹有相同的文件和子文件夹。

             添加文件夹:把磁盘上某个文件夹的添加进来,包括了文件夹的文件和它的所有子文件夹的文件。

             删除文件夹:把该文件夹的内容(包括文件和文件夹)删除。

             添加文件:把一个或多个文件添加到文件夹中。

             删除文件:把一个或多个文件删除。

    不过像vs里面的复制,剪切,粘贴,拖拽这些功能就没有实现了。

    介绍了工具的功能到介绍工具的实现了

    下面则是所用到的类和它的体系结构图

    这里的类大致上与之前的差不多,GUIDCreater是生成GUID值的;SpecialCharacter是记录处理一些特殊字符的;RegexCollection是存放着一些公共的正则表达式。GUIDCreater和SpecialCharacter的源码跟上次的一样。SetupFileInfo,SetupHierarchy,SetupDirectoryInfo这三个类又要唠叨一下。

    带Setup开头的几个类,就是vdproj文件里面几个数据项的类,这次就新增了一个SetupHierachy类。这些类存放着各种对象的信息,以及一些自身的方法。

    由平时对文件系统的理解和对vdproj文件的分析,得出这三个类的关系是这样的:

    • SetupDirectoryInfo对象包含有若干个SetupDirectoryInfo对象和若干个SetupFileInfo对象;
    • 一个SetupFileInfo对象只对应这一个SetupHierarchy对象;

    因此SetupDirectoryInfo中应该要有一个存放SetupDirectoryInfo对象的集合和一个SetupFileInfo对象的集合;SetupFileInfo中有一个字段存放与之对应的SetupHierarchy对象。

    这三个类的字段与属性定义如下

    SetupHierarchy类的

     1         public string MsmKey { get; set; }
     2 
     3         private string _ownerKey;
     4         public string  OwnerKey 
     5         {
     6             get 
     7             {
     8                 if (string.IsNullOrEmpty(_ownerKey))
     9                     _ownerKey = "_UNDEFINED";
    10                 return _ownerKey;
    11             }
    12             set
    13             {
    14                 _ownerKey = value;
    15             }
    16         }
    17 
    18         private string _msnSig;
    19         public string MsmSig
    20         {
    21             get
    22             {
    23                 if (string.IsNullOrEmpty(_msnSig))
    24                     _msnSig = "_UNDEFINED";
    25                 return _msnSig;
    26             }
    27             set
    28             {
    29                 _msnSig = value;
    30             } 
    31         }

    SetupFileInfo类的

    1         public string GUID_1
    2         { get { return "1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE"; } }
    3         public string SourcePath { get; set; }
    4         public string TargetName { get; set; }
    5         public string Folder { get; set; }
    6         public string GUID_2 { get; set; }
    7         public SetupHierarchy Hierachy { get; set; }

    SetupDirectoryInfo类的

    1  public static string GUID_1
    2         { get { return "9EF0B969-E518-4E46-987F-47570745A589"; } }
    3         public string GUID_2 { get; set; }
    4         public string Property { get; set; }
    5         public string Name { get; set; }
    6         public List<SetupDirectoryInfo> Folders { get; set; }
    7         public List<SetupFileInfo> Files { get; set; }

    对这三个类的其他成员,就是把vdproj文件提取出来构造对象的方法还有把对象转换成字符串的方法。

             整个工具的核心就是一个ExplorerCore类,它处理着整个各种业务,包括对vdproj的分析,增删改文件夹;它还管理所有文件夹,文件对象;

             对于管理文件夹和文件,ExplorerCore这个核心类使用了6个集合和2个对象,分别是

    • DirDictionary(文件夹字典集):利用文件夹对象SetupDirecotryInfo中GUID2值作为键值的字典集,目的在于能通过GUID值方便获取到文件夹对象
    • DirFile(文件字典集):利用文件对象SetupFileInfo中GUID2值作为键值的字典集,目的在于能通过GUID值方便获取到文件对象
    • FileList(文件列表):文件对象SetupFileInfo的列表,在生成所有文件的字符串时遍历使用。
    • OrgHierachyList(无对应文件的Hierachy列表):存放着未与文件对应的Hierachy对象,刚从vdproj文件分析出来的Hierachy对象都先存放在此集合。
    • OwnerHierachyList(有对应文件的Hierachy列表):存放着已于文件对应的Hierachy对象。
    • GarbageGUID(已经废弃的GUID列表):存放着已被删除的文件或文件夹的GUID值
    • OtherFiles(一些解析不成功的文件信息):以字符串的形式存放着解析不出来的文件信息
    • RootFolder(根文件夹对象):整个文件系统树形结构的根,也就是“应用程序文件夹”的对象。

      经过多次的实践得出,这个文件或文件夹的唯一标识码GUID值在vdproj文件中有很大的作用,文件和文件夹通过它进行关联,程序的快捷方式通过它跟指定的文件、文件夹进行关联。因此在删除一个文件或文件夹之后,一定要被删除的对象的GUID值记录起来。等到保存成vdproj的之后统一把文件存在的废弃GUID码删除替换掉。否则保存之后如果vdproj还存在着废弃的GUID码,vs会打不开那个vdproj文件的。

      ExplorerCore这个核心类的方法就不逐一介绍了,到本文最后就会把整个类的代码粘贴出来。工具写出来了,毛病还是有的,不过至少满足现在的使用需求,能让我打包方便点儿,对类的分析好像还很混乱,有些地方为啥要这样做我也说不清楚(就比如那个SetupHierarchy的对象啥要分开成与文件关联和未与文件关联两个列表存放),还有一个弊病就是产生的字符串太多了,对GC不怎么友好。还有本文的思路很不清晰,呵呵,莫怪。

      1     class ExplorerCore
      2     {
      3         private string FileFullName { get; set; }
      4         private SetupDirectoryInfo RootFolder { get; set; }
      5 
      6         private string _otherFiles;
      7         private string OtherFiles 
      8         {
      9             get
     10             {
     11                 if (string.IsNullOrEmpty(_otherFiles))
     12                 {
     13                     string vdpproj = File.ReadAllText(FileFullName, Encoding.UTF8);
     14                     _otherFiles = Regex.Match(vdpproj, RegexCollection.RegFilesInner).Value;
     15                     _otherFiles = Regex.Replace(_otherFiles, RegexCollection.RegFileString, "");
     16                     _otherFiles = Regex.Replace(_otherFiles, @"s+
    ", "");
     17                     if (string.IsNullOrEmpty(_otherFiles))
     18                         _otherFiles = "
    ";
     19                 }
     20                 return "
    "+_otherFiles+"
    ";
     21             }
     22         }
     23 
     24         private Dictionary<string, SetupDirectoryInfo> _dirDictionary;
     25         private Dictionary<string, SetupDirectoryInfo> DirDictionary
     26         {
     27             get
     28             {
     29                 if (_dirDictionary == null)
     30                     _dirDictionary = new Dictionary<string, SetupDirectoryInfo>();
     31                 return _dirDictionary;
     32             }
     33         }
     34 
     35 
     36         private Dictionary<string, SetupFileInfo> _dirFile;
     37         private Dictionary<string, SetupFileInfo> DirFile
     38         {
     39             get
     40             {
     41                 if (_dirFile == null)
     42                     _dirFile =new Dictionary<string, SetupFileInfo>();
     43                 return _dirFile;
     44             }
     45         }
     46 
     47         private List<SetupFileInfo> _fileList;
     48         private List<SetupFileInfo> FileList
     49         {
     50             get
     51             {
     52                 if (_fileList == null)
     53                     _fileList = new List<SetupFileInfo>();
     54                 return _fileList;
     55             }
     56         }
     57 
     58         private List<SetupHierarchy> _orgHierachyList;
     59         private List<SetupHierarchy> OrgHierachyList
     60         {
     61             get
     62             {
     63                 if (_orgHierachyList == null)
     64                     _orgHierachyList = new List<SetupHierarchy>();
     65                 return _orgHierachyList;
     66             }
     67         }
     68 
     69         private List<SetupHierarchy> _ownerHierachyList;
     70         private List<SetupHierarchy> OwnerHierachyList
     71         {
     72             get
     73             {
     74                 if (_ownerHierachyList == null)
     75                     _ownerHierachyList = new List<SetupHierarchy>();
     76                 return _ownerHierachyList;
     77             }
     78         }
     79 
     80         private List<string> _garbageGUID;
     81         private List<string> GarbageGUID
     82         {
     83             get
     84             {
     85                 if (_garbageGUID == null)
     86                     _garbageGUID = new List<string>();
     87                 return _garbageGUID;
     88             }
     89         }
     90 
     91         private void GCGUID(string guid)
     92         {
     93             if (GarbageGUID.Contains(guid)) return;
     94             GarbageGUID.Add(guid);
     95         }
     96 
     97         /// <summary>
     98         /// 增加文件夹到集合中
     99         /// </summary>
    100         /// <param name="info"></param>
    101         private void AddDirectory(SetupDirectoryInfo info)
    102         {
    103             if (!DirDictionary.ContainsKey(info.GUID_2))
    104                 DirDictionary.Add(info.GUID_2, info);
    105         }
    106 
    107         /// <summary>
    108         /// 增加文件到其所属文件夹中
    109         /// </summary>
    110         /// <param name="info"></param>
    111         private void AddFileToDircotory(SetupFileInfo info)
    112         {
    113             if (DirDictionary.ContainsKey(info.Folder) &&
    114                 !DirDictionary[info.Folder].Files.Contains(info))
    115                 DirDictionary[info.Folder].Files.Add(info);
    116         }
    117 
    118         /// <summary>
    119         /// 增加文件到文件列表中
    120         /// </summary>
    121         /// <param name="info"></param>
    122         private void AddFile(SetupFileInfo info)
    123         {
    124             FileList.Add(info);
    125             DirFile.Add(info.GUID_2, info);
    126         }
    127 
    128         /// <summary>
    129         /// 把文件夹 文件 Hierachy组合在一起
    130         /// </summary>
    131         private void CombineObjects()
    132         {
    133             foreach (SetupFileInfo item in FileList)
    134                 AddFileToDircotory(item);
    135 
    136             for (int i = 0; i < _orgHierachyList.Count; i++)
    137             {
    138                 if (DirFile.ContainsKey(OrgHierachyList[i].MsmKey))
    139                 {
    140                     DirFile[OrgHierachyList[i].MsmKey].Hierachy = OrgHierachyList[i];
    141                     OwnerHierachyList.Add(OrgHierachyList[i]);
    142                     OrgHierachyList.RemoveAt(i);
    143                     i--;
    144                 }
    145             }
    146         }
    147 
    148         /// <summary>
    149         /// 初始化读入文档内容,分析并构建起树
    150         /// </summary>
    151         /// <param name="fileName"></param>
    152         /// <returns></returns>
    153         public SetupDirectoryInfo InitExplorer(string fileName)
    154         {
    155             FileFullName = fileName;
    156             string vdprojContent = File.ReadAllText(fileName, Encoding.UTF8);
    157 
    158             string strFolder = Regex.Match(vdprojContent, RegexCollection.RegFoldersInner).Value;
    159             SetupDirectoryInfo root = new SetupDirectoryInfo()
    160             {
    161                 GUID_2 = Regex.Match(vdprojContent, RegexCollection.RegAppFolderGuid2).Value,
    162                 Name = "应用程序文件夹",
    163                 Files = new List<SetupFileInfo>(),
    164                 Folders = new List<SetupDirectoryInfo>()
    165             };
    166             RootFolder = root;
    167             AddDirectory(root);
    168             SetupDirectoryInfo.CreateSetupDirectoryInfo(strFolder, root,this.DirDictionary);
    169 
    170             string strFiles = Regex.Match(vdprojContent, RegexCollection.RegFilesInner).Value;
    171             MatchCollection fileMatch = Regex.Matches(strFiles, RegexCollection.RegFileString);
    172             foreach (Match item in fileMatch)
    173                 AddFile(SetupFileInfo.CreateSetupFileInfo(item.Value));
    174 
    175             string strHierachy = Regex.Match(vdprojContent, RegexCollection.RegHierachyInner).Value;
    176             MatchCollection hierachyMatch = Regex.Matches(strHierachy, RegexCollection.RegHierarchy);
    177             foreach (Match item in hierachyMatch)
    178                 OrgHierachyList.Add(SetupHierarchy.CreateHierarchy(item.Value));
    179 
    180             CombineObjects();
    181             return root;
    182         }
    183 
    184         /// <summary>
    185         /// 可视化界面 删除文件
    186         /// </summary>
    187         /// <param name="file"></param>
    188         public void DeleteFile(SetupFileInfo file)
    189         {
    190             FileList.Remove(file);
    191             DirFile.Remove(file.GUID_2);
    192             OwnerHierachyList.Remove(file.Hierachy);
    193             DirDictionary[file.Folder].Files.Remove(file);
    194             GCGUID(file.GUID_2);
    195         }
    196 
    197         /// <summary>
    198         /// 可视化界面 增加文件
    199         /// </summary>
    200         /// <param name="dir"></param>
    201         /// <param name="fileInfo"></param>
    202         public void AddFile(SetupDirectoryInfo dir, FileInfo fileInfo)
    203         {
    204             SetupFileInfo file = new SetupFileInfo();
    205 
    206             file.GUID_2 = GUIDCreater.CreateGUID2();
    207             file.SourcePath = fileInfo.FullName.Replace("\", "\\");
    208             file.TargetName = fileInfo.Name;
    209             file.Folder = dir.GUID_2;
    210             file.Hierachy = new SetupHierarchy(file);
    211 
    212             AddFile(file);
    213             AddFileToDircotory(file);
    214             OwnerHierachyList.Add(file.Hierachy);
    215         }
    216 
    217         /// <summary>
    218         /// 可视化界面 删除文件夹
    219         /// </summary>
    220         /// <param name="dir"></param>
    221         public void DeleteDircetory(SetupDirectoryInfo dir,SetupDirectoryInfo parent)
    222         {
    223             //foreach (SetupFileInfo file in dir.Files)
    224             while (dir.Files.Count>0)
    225                 DeleteFile(dir.Files[0]);
    226             //foreach (SetupDirectoryInfo subDir in dir.Folders)
    227             while (dir.Folders.Count>0)
    228                 DeleteDircetory(dir.Folders[0],dir);
    229             parent.Folders.Remove(dir);
    230             DirDictionary.Remove(dir.GUID_2);
    231             GCGUID(dir.GUID_2);
    232         }
    233 
    234         /// <summary>
    235         /// 可视化界面 增加文件夹
    236         /// </summary>
    237         /// <param name="dirInfo"></param>
    238         /// <param name="dir"></param>
    239         public void AddDirectory(SetupDirectoryInfo dirInfo, DirectoryInfo dir)
    240         {
    241 
    242             SetupDirectoryInfo currDir = new SetupDirectoryInfo();
    243             currDir.Name = dir.Name;
    244             currDir.GUID_2 = GUIDCreater.CreateGUID2();
    245             currDir.Property = GUIDCreater.CreateGUID2();
    246             currDir.Files = new List<SetupFileInfo>();
    247             currDir.Folders = new List<SetupDirectoryInfo>();
    248 
    249             DirectoryInfo[] dirs = dir.GetDirectories();
    250             List<SetupDirectoryInfo> folderList = new List<SetupDirectoryInfo>(dirs.Length);
    251             foreach (DirectoryInfo item in dirs)
    252                 AddDirectory(currDir, item);
    253             AddDirectory(currDir);
    254             dirInfo.Folders.Add(currDir);
    255 
    256             FileInfo[] files = dir.GetFiles();
    257             List<SetupFileInfo> fileList = new List<SetupFileInfo>(files.Length);
    258             foreach (FileInfo file in files)
    259                 AddFile(currDir, file);
    260         }
    261 
    262         /// <summary>
    263         /// 可视化界面 同步文件夹
    264         /// </summary>
    265         /// <param name="dirInfo"></param>
    266         /// <param name="dir"></param>
    267         public void SynDirectory(SetupDirectoryInfo dirInfo, DirectoryInfo dir)
    268         {
    269             DirectoryInfo[] dirArry = dir.GetDirectories();
    270             List<SetupDirectoryInfo> newDirList = new List<SetupDirectoryInfo>(dirArry.Length);
    271             SetupDirectoryInfo newDir = null;
    272             foreach (DirectoryInfo item in dirArry)
    273             {
    274                 newDir = dirInfo.ExistSubDirectory(item.Name);
    275                 if (newDir != null)
    276                 {
    277                     newDirList.Add(newDir);
    278                     dirInfo.Folders.Remove(newDir);
    279                 }
    280                 else
    281                 {
    282                     newDir = new SetupDirectoryInfo();
    283                     newDir.Name = item.Name;
    284                     newDir.GUID_2 = GUIDCreater.CreateGUID2();
    285                     newDir.Property = GUIDCreater.CreateGUID2();
    286                     newDir.Files = new List<SetupFileInfo>();
    287                     newDir.Folders = new List<SetupDirectoryInfo>();
    288 
    289                     AddDirectory(newDir);
    290                     newDirList.Add(newDir);
    291                 }
    292                 SynDirectory(newDir, item);
    293             }
    294             while (dirInfo.Folders.Count > 0)
    295                 DeleteDircetory(dirInfo.Folders[0], dirInfo);
    296             dirInfo.Folders = newDirList;
    297 
    298             FileInfo[] fileArry = dir.GetFiles();
    299             List<SetupFileInfo> newFileList = new List<SetupFileInfo>(fileArry.Length);
    300             SetupFileInfo newFile = null;
    301             foreach (FileInfo item in fileArry)
    302             {
    303                 newFile = dirInfo.ExistFile(item.Name);
    304                 if (newFile != null)
    305                 {
    306                     newFile.SourcePath = item.FullName.Replace("\", "\\");
    307                     newFileList.Add(newFile);
    308                     dirInfo.Files.Remove(newFile);
    309                 }
    310                 else
    311                 {
    312                     SetupFileInfo file = new SetupFileInfo();
    313 
    314                     file.GUID_2 = GUIDCreater.CreateGUID2();
    315                     file.SourcePath = item.FullName.Replace("\", "\\");
    316                     file.TargetName = item.Name;
    317                     file.Folder = dirInfo.GUID_2;
    318                     file.Hierachy = new SetupHierarchy(file);
    319 
    320                     AddFile(file);
    321                     //AddFileToDircotory(file);
    322                     newFileList.Add(file);
    323                     OwnerHierachyList.Add(file.Hierachy);
    324                 }
    325                     //AddFile(dirInfo, item);
    326             }
    327             while (dirInfo.Files.Count > 0)
    328                 DeleteFile(dirInfo.Files[0]);
    329             dirInfo.Files = newFileList;
    330 
    331         }
    332 
    333         public void SaveFile()
    334         {
    335             Initial();
    336             StringBuilder sbFile = new StringBuilder();
    337             foreach (SetupFileInfo item in FileList)
    338                 sbFile.Append(item.CreateFileItemInfo());
    339             sbFile.Append(OtherFiles);
    340 
    341             StringBuilder sbHierachy=new StringBuilder();
    342             foreach (SetupHierarchy item in OwnerHierachyList)
    343                 sbHierachy.Append(item.ToString());
    344             foreach (SetupHierarchy item in OrgHierachyList)
    345                 sbHierachy.Append(item.ToString());
    346 
    347             //string strFolders = RootFolder.CreateFoldersString();
    348             StringBuilder sbFolder = new StringBuilder();
    349             foreach (SetupDirectoryInfo item in RootFolder.Folders)
    350                 sbFolder.Append(item.CreateFoldersString());
    351 
    352             string vdprojContent = SpecialCharacter.ChangeSpecialCharacter(File.ReadAllText(FileFullName, Encoding.UTF8));
    353             File.Copy(FileFullName, FileFullName + ".bak", true);
    354 
    355             vdprojContent =SpecialCharacter.RecoverSpecialCharacter( OverWriteContent(vdprojContent,
    356                SpecialCharacter.ChangeSpecialCharacter( sbHierachy.ToString()),
    357                 SpecialCharacter.ChangeSpecialCharacter( sbFile.ToString()),
    358                SpecialCharacter.ChangeSpecialCharacter( sbFolder.ToString())
    359             ));
    360             vdprojContent= SafeCheckGUID(vdprojContent);
    361             File.WriteAllText(FileFullName, vdprojContent, Encoding.UTF8);
    362             Finish();
    363         }
    364 
    365 
    366         private string SafeCheckGUID(string vdprojContent)
    367         {
    368             if (_garbageGUID == null) return vdprojContent;
    369             foreach (string guidItem in GarbageGUID)
    370                vdprojContent= vdprojContent.Replace(guidItem, "");
    371             return vdprojContent;
    372         }
    373 
    374         private string OverWriteContent(string vdprojContent, string strHierarchy, string strFiles, string strFolders)
    375         {
    376             vdprojContent = Regex.Replace(vdprojContent, RegexCollection.RegFilesInner, strFiles);
    377             vdprojContent = Regex.Replace(vdprojContent, RegexCollection.RegFoldersInner, strFolders);
    378             vdprojContent = Regex.Replace(vdprojContent, RegexCollection.RegHierachyInner, strHierarchy);
    379 
    380             return vdprojContent;
    381         }
    382 
    383         private void Initial()
    384         {
    385             SpecialCharacter.AddCharacter("$");
    386         }
    387 
    388         private void Finish()
    389         {
    390             SpecialCharacter.ClearRecord();
    391             GC.Collect();
    392         }
    393     }
    ExplorerCore核心类
  • 相关阅读:
    一次心惊肉跳的服务器误删文件的恢复过程
    ThreadPoolExecutor使用详解
    Springboot学习笔记(一)-线程池的简化及使用
    springboot之异步调用@Async
    CentOS 7添加开机启动服务/脚本
    三分钟在任何电脑上使用 chrome os
    Spring Cloud Alibaba基础教程:Sentinel Dashboard中修改规则同步到Nacos
    Nacos部署中的一些常见问题汇总
    Spring Cloud Alibaba基础教程:Sentinel Dashboard中修改规则同步到Apollo
    Spring Cloud Alibaba 新版本发布:众多期待内容整合打包加入!
  • 原文地址:https://www.cnblogs.com/HopeGi/p/3231691.html
Copyright © 2020-2023  润新知