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类的
- public string MsmKey { get; set; }
- private string _ownerKey;
- public string OwnerKey
- {
- get
- {
- if (string.IsNullOrEmpty(_ownerKey))
- _ownerKey = "_UNDEFINED";
- return _ownerKey;
- }
- set
- {
- _ownerKey = value;
- }
- }
- private string _msnSig;
- public string MsmSig
- {
- get
- {
- if (string.IsNullOrEmpty(_msnSig))
- _msnSig = "_UNDEFINED";
- return _msnSig;
- }
- set
- {
- _msnSig = value;
- }
- }
SetupFileInfo类的
- public string GUID_1
- { get { return "1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE"; } }
- public string SourcePath { get; set; }
- public string TargetName { get; set; }
- public string Folder { get; set; }
- public string GUID_2 { get; set; }
- public SetupHierarchy Hierachy { get; set; }
SetupDirectoryInfo类的
- public static string GUID_1
- { get { return "9EF0B969-E518-4E46-987F-47570745A589"; } }
- public string GUID_2 { get; set; }
- public string Property { get; set; }
- public string Name { get; set; }
- public List<SetupDirectoryInfo> Folders { get; set; }
- 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不怎么友好。还有本文的思路很不清晰,呵呵,莫怪。
- class ExplorerCore
- {
- private string FileFullName { get; set; }
- private SetupDirectoryInfo RootFolder { get; set; }
- private string _otherFiles;
- private string OtherFiles
- {
- get
- {
- if (string.IsNullOrEmpty(_otherFiles))
- {
- string vdpproj = File.ReadAllText(FileFullName, Encoding.UTF8);
- _otherFiles = Regex.Match(vdpproj, RegexCollection.RegFilesInner).Value;
- _otherFiles = Regex.Replace(_otherFiles, RegexCollection.RegFileString, "");
- _otherFiles = Regex.Replace(_otherFiles, @"\s+\r\n", "");
- if (string.IsNullOrEmpty(_otherFiles))
- _otherFiles = "\r\n";
- }
- return "\r\n"+_otherFiles+"\r\n";
- }
- }
- private Dictionary<string, SetupDirectoryInfo> _dirDictionary;
- private Dictionary<string, SetupDirectoryInfo> DirDictionary
- {
- get
- {
- if (_dirDictionary == null)
- _dirDictionary = new Dictionary<string, SetupDirectoryInfo>();
- return _dirDictionary;
- }
- }
- private Dictionary<string, SetupFileInfo> _dirFile;
- private Dictionary<string, SetupFileInfo> DirFile
- {
- get
- {
- if (_dirFile == null)
- _dirFile =new Dictionary<string, SetupFileInfo>();
- return _dirFile;
- }
- }
- private List<SetupFileInfo> _fileList;
- private List<SetupFileInfo> FileList
- {
- get
- {
- if (_fileList == null)
- _fileList = new List<SetupFileInfo>();
- return _fileList;
- }
- }
- private List<SetupHierarchy> _orgHierachyList;
- private List<SetupHierarchy> OrgHierachyList
- {
- get
- {
- if (_orgHierachyList == null)
- _orgHierachyList = new List<SetupHierarchy>();
- return _orgHierachyList;
- }
- }
- private List<SetupHierarchy> _ownerHierachyList;
- private List<SetupHierarchy> OwnerHierachyList
- {
- get
- {
- if (_ownerHierachyList == null)
- _ownerHierachyList = new List<SetupHierarchy>();
- return _ownerHierachyList;
- }
- }
- private List<string> _garbageGUID;
- private List<string> GarbageGUID
- {
- get
- {
- if (_garbageGUID == null)
- _garbageGUID = new List<string>();
- return _garbageGUID;
- }
- }
- private void GCGUID(string guid)
- {
- if (GarbageGUID.Contains(guid)) return;
- GarbageGUID.Add(guid);
- }
- /// <summary>
- /// 增加文件夹到集合中
- /// </summary>
- /// <param name="info"></param>
- private void AddDirectory(SetupDirectoryInfo info)
- {
- if (!DirDictionary.ContainsKey(info.GUID_2))
- DirDictionary.Add(info.GUID_2, info);
- }
- /// <summary>
- /// 增加文件到其所属文件夹中
- /// </summary>
- /// <param name="info"></param>
- private void AddFileToDircotory(SetupFileInfo info)
- {
- if (DirDictionary.ContainsKey(info.Folder) &&
- !DirDictionary[info.Folder].Files.Contains(info))
- DirDictionary[info.Folder].Files.Add(info);
- }
- /// <summary>
- /// 增加文件到文件列表中
- /// </summary>
- /// <param name="info"></param>
- private void AddFile(SetupFileInfo info)
- {
- FileList.Add(info);
- DirFile.Add(info.GUID_2, info);
- }
- /// <summary>
- /// 把文件夹 文件 Hierachy组合在一起
- /// </summary>
- private void CombineObjects()
- {
- foreach (SetupFileInfo item in FileList)
- AddFileToDircotory(item);
- for (int i = ; i < _orgHierachyList.Count; i++)
- {
- if (DirFile.ContainsKey(OrgHierachyList[i].MsmKey))
- {
- DirFile[OrgHierachyList[i].MsmKey].Hierachy = OrgHierachyList[i];
- OwnerHierachyList.Add(OrgHierachyList[i]);
- OrgHierachyList.RemoveAt(i);
- i--;
- }
- }
- }
- /// <summary>
- /// 初始化读入文档内容,分析并构建起树
- /// </summary>
- /// <param name="fileName"></param>
- /// <returns></returns>
- public SetupDirectoryInfo InitExplorer(string fileName)
- {
- FileFullName = fileName;
- string vdprojContent = File.ReadAllText(fileName, Encoding.UTF8);
- string strFolder = Regex.Match(vdprojContent, RegexCollection.RegFoldersInner).Value;
- SetupDirectoryInfo root = new SetupDirectoryInfo()
- {
- GUID_2 = Regex.Match(vdprojContent, RegexCollection.RegAppFolderGuid2).Value,
- Name = "应用程序文件夹",
- Files = new List<SetupFileInfo>(),
- Folders = new List<SetupDirectoryInfo>()
- };
- RootFolder = root;
- AddDirectory(root);
- SetupDirectoryInfo.CreateSetupDirectoryInfo(strFolder, root,this.DirDictionary);
- string strFiles = Regex.Match(vdprojContent, RegexCollection.RegFilesInner).Value;
- MatchCollection fileMatch = Regex.Matches(strFiles, RegexCollection.RegFileString);
- foreach (Match item in fileMatch)
- AddFile(SetupFileInfo.CreateSetupFileInfo(item.Value));
- string strHierachy = Regex.Match(vdprojContent, RegexCollection.RegHierachyInner).Value;
- MatchCollection hierachyMatch = Regex.Matches(strHierachy, RegexCollection.RegHierarchy);
- foreach (Match item in hierachyMatch)
- OrgHierachyList.Add(SetupHierarchy.CreateHierarchy(item.Value));
- CombineObjects();
- return root;
- }
- /// <summary>
- /// 可视化界面 删除文件
- /// </summary>
- /// <param name="file"></param>
- public void DeleteFile(SetupFileInfo file)
- {
- FileList.Remove(file);
- DirFile.Remove(file.GUID_2);
- OwnerHierachyList.Remove(file.Hierachy);
- DirDictionary[file.Folder].Files.Remove(file);
- GCGUID(file.GUID_2);
- }
- /// <summary>
- /// 可视化界面 增加文件
- /// </summary>
- /// <param name="dir"></param>
- /// <param name="fileInfo"></param>
- public void AddFile(SetupDirectoryInfo dir, FileInfo fileInfo)
- {
- SetupFileInfo file = new SetupFileInfo();
- file.GUID_2 = GUIDCreater.CreateGUID2();
- file.SourcePath = fileInfo.FullName.Replace("\\", "\\\\");
- file.TargetName = fileInfo.Name;
- file.Folder = dir.GUID_2;
- file.Hierachy = new SetupHierarchy(file);
- AddFile(file);
- AddFileToDircotory(file);
- OwnerHierachyList.Add(file.Hierachy);
- }
- /// <summary>
- /// 可视化界面 删除文件夹
- /// </summary>
- /// <param name="dir"></param>
- public void DeleteDircetory(SetupDirectoryInfo dir,SetupDirectoryInfo parent)
- {
- //foreach (SetupFileInfo file in dir.Files)
- while (dir.Files.Count>)
- DeleteFile(dir.Files[]);
- //foreach (SetupDirectoryInfo subDir in dir.Folders)
- while (dir.Folders.Count>)
- DeleteDircetory(dir.Folders[],dir);
- parent.Folders.Remove(dir);
- DirDictionary.Remove(dir.GUID_2);
- GCGUID(dir.GUID_2);
- }
- /// <summary>
- /// 可视化界面 增加文件夹
- /// </summary>
- /// <param name="dirInfo"></param>
- /// <param name="dir"></param>
- public void AddDirectory(SetupDirectoryInfo dirInfo, DirectoryInfo dir)
- {
- SetupDirectoryInfo currDir = new SetupDirectoryInfo();
- currDir.Name = dir.Name;
- currDir.GUID_2 = GUIDCreater.CreateGUID2();
- currDir.Property = GUIDCreater.CreateGUID2();
- currDir.Files = new List<SetupFileInfo>();
- currDir.Folders = new List<SetupDirectoryInfo>();
- DirectoryInfo[] dirs = dir.GetDirectories();
- List<SetupDirectoryInfo> folderList = new List<SetupDirectoryInfo>(dirs.Length);
- foreach (DirectoryInfo item in dirs)
- AddDirectory(currDir, item);
- AddDirectory(currDir);
- dirInfo.Folders.Add(currDir);
- FileInfo[] files = dir.GetFiles();
- List<SetupFileInfo> fileList = new List<SetupFileInfo>(files.Length);
- foreach (FileInfo file in files)
- AddFile(currDir, file);
- }
- /// <summary>
- /// 可视化界面 同步文件夹
- /// </summary>
- /// <param name="dirInfo"></param>
- /// <param name="dir"></param>
- public void SynDirectory(SetupDirectoryInfo dirInfo, DirectoryInfo dir)
- {
- DirectoryInfo[] dirArry = dir.GetDirectories();
- List<SetupDirectoryInfo> newDirList = new List<SetupDirectoryInfo>(dirArry.Length);
- SetupDirectoryInfo newDir = null;
- foreach (DirectoryInfo item in dirArry)
- {
- newDir = dirInfo.ExistSubDirectory(item.Name);
- if (newDir != null)
- {
- newDirList.Add(newDir);
- dirInfo.Folders.Remove(newDir);
- }
- else
- {
- newDir = new SetupDirectoryInfo();
- newDir.Name = item.Name;
- newDir.GUID_2 = GUIDCreater.CreateGUID2();
- newDir.Property = GUIDCreater.CreateGUID2();
- newDir.Files = new List<SetupFileInfo>();
- newDir.Folders = new List<SetupDirectoryInfo>();
- AddDirectory(newDir);
- newDirList.Add(newDir);
- }
- SynDirectory(newDir, item);
- }
- while (dirInfo.Folders.Count > )
- DeleteDircetory(dirInfo.Folders[], dirInfo);
- dirInfo.Folders = newDirList;
- FileInfo[] fileArry = dir.GetFiles();
- List<SetupFileInfo> newFileList = new List<SetupFileInfo>(fileArry.Length);
- SetupFileInfo newFile = null;
- foreach (FileInfo item in fileArry)
- {
- newFile = dirInfo.ExistFile(item.Name);
- if (newFile != null)
- {
- newFile.SourcePath = item.FullName.Replace("\\", "\\\\");
- newFileList.Add(newFile);
- dirInfo.Files.Remove(newFile);
- }
- else
- {
- SetupFileInfo file = new SetupFileInfo();
- file.GUID_2 = GUIDCreater.CreateGUID2();
- file.SourcePath = item.FullName.Replace("\\", "\\\\");
- file.TargetName = item.Name;
- file.Folder = dirInfo.GUID_2;
- file.Hierachy = new SetupHierarchy(file);
- AddFile(file);
- //AddFileToDircotory(file);
- newFileList.Add(file);
- OwnerHierachyList.Add(file.Hierachy);
- }
- //AddFile(dirInfo, item);
- }
- while (dirInfo.Files.Count > )
- DeleteFile(dirInfo.Files[]);
- dirInfo.Files = newFileList;
- }
- public void SaveFile()
- {
- Initial();
- StringBuilder sbFile = new StringBuilder();
- foreach (SetupFileInfo item in FileList)
- sbFile.Append(item.CreateFileItemInfo());
- sbFile.Append(OtherFiles);
- StringBuilder sbHierachy=new StringBuilder();
- foreach (SetupHierarchy item in OwnerHierachyList)
- sbHierachy.Append(item.ToString());
- foreach (SetupHierarchy item in OrgHierachyList)
- sbHierachy.Append(item.ToString());
- //string strFolders = RootFolder.CreateFoldersString();
- StringBuilder sbFolder = new StringBuilder();
- foreach (SetupDirectoryInfo item in RootFolder.Folders)
- sbFolder.Append(item.CreateFoldersString());
- string vdprojContent = SpecialCharacter.ChangeSpecialCharacter(File.ReadAllText(FileFullName, Encoding.UTF8));
- File.Copy(FileFullName, FileFullName + ".bak", true);
- vdprojContent =SpecialCharacter.RecoverSpecialCharacter( OverWriteContent(vdprojContent,
- SpecialCharacter.ChangeSpecialCharacter( sbHierachy.ToString()),
- SpecialCharacter.ChangeSpecialCharacter( sbFile.ToString()),
- SpecialCharacter.ChangeSpecialCharacter( sbFolder.ToString())
- ));
- vdprojContent= SafeCheckGUID(vdprojContent);
- File.WriteAllText(FileFullName, vdprojContent, Encoding.UTF8);
- Finish();
- }
- private string SafeCheckGUID(string vdprojContent)
- {
- if (_garbageGUID == null) return vdprojContent;
- foreach (string guidItem in GarbageGUID)
- vdprojContent= vdprojContent.Replace(guidItem, "");
- return vdprojContent;
- }
- private string OverWriteContent(string vdprojContent, string strHierarchy, string strFiles, string strFolders)
- {
- vdprojContent = Regex.Replace(vdprojContent, RegexCollection.RegFilesInner, strFiles);
- vdprojContent = Regex.Replace(vdprojContent, RegexCollection.RegFoldersInner, strFolders);
- vdprojContent = Regex.Replace(vdprojContent, RegexCollection.RegHierachyInner, strHierarchy);
- return vdprojContent;
- }
- private void Initial()
- {
- SpecialCharacter.AddCharacter("$");
- }
- private void Finish()
- {
- SpecialCharacter.ClearRecord();
- GC.Collect();
- }
- }
ExplorerCore核心类
mis导入器的加强版——vdproj文件资源浏览器的更多相关文章
- 防止SpringMVC拦截器拦截js等静态资源文件
SpringMVC提供<mvc:resources>来设置静态资源,但是增加该设置如果采用通配符的方式增加拦截器的话仍然会被拦截器拦截,可采用如下方案进行解决: 方案一.拦截器中增加针对静 ...
- 在JSP中常见问题,防止SpringMVC拦截器拦截js等静态资源文件的解决方案
方案一.拦截器中增加针对静态资源不进行过滤(涉及spring-mvc.xml) <mvc:resources location="/" mapping="/**/* ...
- JavaWeb中读取文件资源的路径问题
在做javaweb开发的时候,我们可能会需要从本地硬盘上读取某一个文件资源,或者修改某一个文件,这个时候就需要先找到这个文件,然后用FileInputStrem等文件字节.字符流来将这个文件读取到内存 ...
- VS编辑代码的时候,都会自动在资源浏览器里将文件所在项目展开
如何设置VS编辑代码的时候,都会自动在资源浏览器里将文件所在项目展开 工具-选项-项目和解决方案-常规-在解决方案资源管理器中跟踪活动项(C)
- 文件批量上传-统一附件管理器-在线预览文件(有互联网和没有两种)--SNF快速开发平台3.0
实际上在SNF里使用附件管理是非常简单的事情,一句代码就可以搞定.但我也要在这里记录一下统一附件管理器能满足的需求. 通用的附件管理,不要重复开发,调用尽量简洁. 批量文件上传,并对每个文件大小限制, ...
- JavaWeb中读取文件资源的路径问题 -- 转自新浪博客
在做javaweb开发的时候,我们可能会需要从本地硬盘上读取某一个文件资源,或者修改某一个文件,这个时候就需要先找到这个文件,然后用FileInputStrem等文件字节.字符流来将这个文件读取到内存 ...
- Excel 通过pl/sql导入到数据库 文本导入器 odbc导入器
Excel 通过pl/sql导入到数据库 第一种方法:文本导入器 1.准备Excel导入数据 jc.xls 2.把 jc.xls 文件 改为 jc.csv文件 3.在数据库里建一张jc表(FLH ...
- atitit.sql server2008导出导入数据库大的表格文件... oracle mysql
atitit.sql server2008导出导入数据库大的表格文件... 1. 超过80M的文件是不能在查询分析器中执行的 1 2. Oracle ,mysql大的文件导入 1 2.1. 使用sql ...
- 解决Ubuntu14.04下Clementine音乐播放器不能播放wma文件的问题
参考:Ubuntu 14.04 安装深度音乐的方法 问题描述:播放wma文件时提示"GStreamer插件未安装". 解决方法:安装gstreamer-ffmpeg插件即可解决问题 ...
随机推荐
- THinkphp开启静态(动态)缓存的用法
<?php return array( //开启静态缓存 'HTML_CACHE_ON' => true, 'HTML_CACHE_RULES' => array( 'News:in ...
- UiAutomator源代码分析之UiAutomatorBridge框架
上一篇文章<UIAutomator源代码分析之启动和执行>我们描写叙述了uitautomator从命令行执行到载入測试用例执行測试的整个流程.过程中我们也描写叙述了UiAutomatorB ...
- 11G RAC 中 OCR 及Voting Disk 相关操作
一.启动oracle clusterware先决条件:Oracle High Availability Services daemon(OHASD)运行在所有集群节点上1.启动整个Oracle Clu ...
- 【jquery】Validform,一款不错的 jquery 表单验证插件
关于 Validform 这是一款很不错的 jquery 表单验证插件,它几乎能够满足任何验证需求,仅仅一行代码就能搞定整站的表单验证. $('form').Validform(); 为什么能如此方便 ...
- Android 6.0 源代码编译实践
http://www.judymax.com/archives/1087 Android 6.0 源代码编译实践 https://mirrors.tuna.tsinghua.edu.cn/help/A ...
- LeetCode: Unique Paths 解题报告
A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). The ...
- 深入解析DC/OS 1.8 – 高可靠的微服务及大数据管理平台
深入解析DC/OS 1.8 – 高可靠的微服务及大数据管理平台 大家好,欢迎大家参加这次DC/OS的技术分享. 先做个自我介绍,刘超,Linker Networks首席架构师,Open DC/OS社区 ...
- 编译 curl with ssl
安装 openssh后,使用 curl 的 ./configure --with-ssl 时,报错“找不到 ssl”.因为 curl在 /usr/local/ssl的安装目录下找动态连接库.而ssl默 ...
- [原创]HierarchyView的实现原理和Android设备无法使用HierarchyView的解决方法
最近在看一个老外写的东西,发现里面有个类,使用这个类可以让任何设备使用HierarchyView. 众所周知,市面上卖的Android设备,一般都不能使用HierarchyView,所以借此机会,了解 ...
- [leetcode]Binary Tree Right Side View
好久不写了,最近忙毕业论文呢. 这个题,就是说一个二叉树,你从右边看,你能看到的数有哪些(会被遮挡) 其实抽象出来就是说...二叉树每层最右边的数有哪些.. 那我们按层遍历一次就好了. /** * D ...