Fork me on GitHub
一个打包文件导入器

一个打包文件导入器

不光是敲代码,最近连打包也做了,各种各样的打包要解释:给仪器打包,吃饭时帮同事打包饭菜,给生成好的程序打包。由于这里是博客园,仪器打包和饭菜打包不能说太多,不然有移出首页的危险。之前写了两篇关于安装包制作的博文了,这回继续写与安装包相关的。尽管现在有不少的打包工具,但是还用着VS来打包。

       来说说背景,有这么个程序,他的完整代码我手上没有,每次打包都要搭档生成一份给我,这样就没法在项目输出那里把需要的文件(包括exe)塞进去,只能手动去添加,但是面对着多个文件夹,我只能用老黄牛的办法把它们都加进去。一般情况下,我只会把最新的文件替换过去就算了,不过如果添加了新文件,少添加了打包后的程序会不完整,检查的话又够呛的,我总算想到了一个方法,做个导入器,因为想起以前看过杨中科老师的视频,发现vs的项目文件其实就是个xml文件来的,通过改xml把需要的文件加进去,比手工去加要省事。

       于是我就很兴奋地打开了那个vdproj文件,与C#的项目不同,vdproj里面的结构有点像是json那种的,这样要改的话,就没xml那么简单了。

  经过我的查找,发现文件信息是记录在”Files”{}里面的,举个例子

复制代码
        "File"
        {
      "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_F08947D6FAEF4B8BBC64541285AF3FD3" 
      {
       "SourcePath" = "8:C:\\Users\\HopeGi\\Desktop\\temp\\案例Scork\\17-01\\TestInetAddress.class" 
       "TargetName" = "8:TestInetAddress.class" 
      "Tag" = "8:"
      "Folder" = "8:_4264EA06455D4895BA8C4B6449880985" 
       "Condition " =  "8:" 
            "Transitive" = "11:FALSE" 
            "Vital" = "11:TRUE" 
            "ReadOnly" = "11:FALSE" 
            "Hidden" = "11:FALSE" 
            "System" = "11:FALSE" 
            "Permanent" = "11:FALSE" 
            "SharedLegacy" = "11:FALSE" 
            "PackageAs" = "3:1" 
            "Register" = "3:1" 
            "Exclude" = "11:FALSE" 
            "IsDependency" = "11:FALSE" 
            "IsolateTo" = "8:" 
            }
   }
复制代码

一个文件,就是从第3行到导数第二行结束,这么大堆的信息,我能理解的只有几个

  • SourcePath:文件的源路径
  • TargetName:文件在VS里显示的文件名
  • Folder:解包后所在的文件夹

后来再经过我的探究发现这里的三个GUID码,第一个放在括号里头的,如果放在“应用程序文件夹”里面的,统一是1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE,其他文件夹的我没试过,也不清楚;后面有冒号和下划线跟着的那个(就是F08947D6FAEF4B8BBC64541285AF3FD3),这个是随机生成的,这个随机码作为这个文件的唯一标识,还有另一个用途接下来会说到的;最后Folder的随机码下面也会说到。

  文件夹的话,所有内容都放在”Folder”{}里面的,这里我用到的是“应用程序文件夹”而已。

复制代码
      "{3C67513D-01DD-4637-8A68-80971EB9504F}:_EDF54782651E4E74B7A04AA76C65434E"
            {
            "DefaultLocation" = "8:[ProgramFilesFolder][Manufacturer]\\[ProductName]"
            "Name" = "8:#1925"
            "AlwaysCreate" = "11:FALSE"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Property" = "8:TARGETDIR"
                "Folders"
                {
          }
        }
复制代码

我是靠它的DefaultLocation认出来的,文件夹的子文件夹都是放在”Folders”{}里面的,例如其中一个文件夹的信息就这样子

复制代码
    "{9EF0B969-E518-4E46-987F-47570745A589}:_4264EA06455D4895BA8C4B6449880985" 
    {
      "Name" = "8:17-01" 
      "Property" = "8:_F9CDAE22FD634267992D47E28FAA77E7" 
      "AlwaysCreate" = "11:FALSE"
        "Condition" = "8:"
        "Transitive" = "11:FALSE"
        "Folders" 
            { 
                  
            }
        }
复制代码

 

这里也有三个GUID码,第一个对于放在“应用程序文件夹”里面的,统一是9EF0B969-E518-4E46-987F-47570745A589,而第二个是随机生成一个就行了,但这个是用于标识这个文件夹的,而这个随机码是给文件那个”Folder”用的,至于第三个是"Property"的,我也不清楚它的用途。这里还有两个属性我知道是什么回事

  •        “Name”:文件夹的名字
  •        “Folders”:这个文件夹的子文件夹的集合。

这里还有另外一个东西"Hierarchy"{},有了这个,添加的文件才能在解决方案管理器显示出来。每一项的格式如下

"Entry"
{
"MsmKey" = "8:_F08947D6FAEF4B8BBC64541285AF3FD3"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}

这里有只有一个属性我知道是什么意思,不知道的就按回原样就行了,至于"MsmKey"这个就是对应文件的那个GUID码。

好了,了解了vdproj文件的结构之后,就可以通过代码改写vdproj文件,从而实现导入的效果。流程如下

  1. 分析需要导入的目录结构,包括文件夹的层次和文件
  2. 生成与vdproj格式相同的文件夹信息和文件信息
  3. 利用正则找出File,Folder,Hierachy这三部分的信息
  4. 替换vdproj文件的内容

这里要插一句,觉得VS分析vdproj的格式限制得太死了,就连"OwnerKey" = "8:_UNDEFINED"这类的,如果等号两边没有了空格,VS会分析不出来。

最后就介绍源码了。首先是两个实体类,分别用于记录文件夹信息和文件信息的

复制代码
 1     class SetupFileInfo
 2     {
 3         public string GUID_1
 4         { get { return "1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE"; } }
 5         public string SourcePath { get; set; }
 6         public string TargetName { get; set; }
 7         public string Folder { get; set; }
 8         public string GUID_2 { get; set; }
 9 
10         #region 文字模板
11         private static string _defaultString = @" ""Condition "" =  ""8:"" 
12             ""Transitive"" = ""11:FALSE"" 
13             ""Vital"" = ""11:TRUE"" 
14             ""ReadOnly"" = ""11:FALSE"" 
15             ""Hidden"" = ""11:FALSE"" 
16             ""System"" = ""11:FALSE"" 
17             ""Permanent"" = ""11:FALSE"" 
18             ""SharedLegacy"" = ""11:FALSE"" 
19             ""PackageAs"" = ""3:1"" 
20             ""Register"" = ""3:1"" 
21             ""Exclude"" = ""11:FALSE"" 
22             ""IsDependency"" = ""11:FALSE"" 
23             ""IsolateTo"" = ""8:"" 
24             }
25             ";
26         #endregion
27 
28         /// <summary>
29         /// 生成vdproj的文件的字符串
30         /// </summary>
31         /// <returns></returns>
32         public string CreateFileItemInfo()
33         {
34             StringBuilder sb = new StringBuilder();
35             sb.AppendFormat("\r\n\"{{{0}}}:{1}\" \r\n", GUID_1, GUID_2);
36             sb.AppendFormat("{{\r\n \"SourcePath\" = \"8:{0}\" \r\n", SourcePath);
37             sb.AppendFormat("\"TargetName\" = \"8:{0}\" \r\n", TargetName);
38             sb.AppendLine("\"Tag\" = \"8:\"");
39             sb.AppendFormat("\"Folder\" = \"8:{0}\" \r\n",Folder);
40             sb.AppendLine(_defaultString);
41 
42             return sb.ToString();
43         }
44     }
复制代码
复制代码
 1     class SetupDirectoryInfo
 2     {
 3         public static string GUID_1
 4         { get { return "9EF0B969-E518-4E46-987F-47570745A589"; } }
 5         public string GUID_2 { get; set; }
 6         public string Property { get; set; }
 7         public string Name { get; set; }
 8         public List<SetupDirectoryInfo> Folders { get; set; }
 9         public List<SetupFileInfo> Files { get; set; }
10 
11         /// <summary>
12         /// 生成当前目录和子目录的所有文件的字符串
13         /// </summary>
14         /// <returns></returns>
15         internal string CreateFilesString()
16         {
17             StringBuilder sb = new StringBuilder();
18 
19             foreach (SetupFileInfo item in Files)
20                 sb.Append(item.CreateFileItemInfo());
21 
22             foreach (SetupDirectoryInfo item in Folders)
23                 sb.Append(item.CreateFilesString());
24 
25             return sb.ToString();
26         }
27         
28         /// <summary>
29         /// 生成当前目录及子目录的文件夹字符串
30         /// </summary>
31         /// <returns></returns>
32         internal string CreateFoldersString()
33         {
34             StringBuilder sb = new StringBuilder();
35             foreach (SetupDirectoryInfo item in Folders)
36                 sb.Append(item.CreateFoldersString());
37 
38             string result = BuildCurrentFolderString().Replace("$$", sb.ToString());
39             return result;
40         }
41 
42         /// <summary>
43         /// 供解决方案资源管理器用
44         /// </summary>
45         /// <returns></returns>
46         internal string CreateHierarchyString()
47         {
48             StringBuilder sb = new StringBuilder(); 
49             foreach (SetupFileInfo file in Files)
50             {
51                 sb.AppendLine("\r\n\"Entry\"\r\n{");
52                 sb.AppendFormat("\"MsmKey\" = \"8:{0}\"\r\n",file.GUID_2);
53                 sb.AppendLine("\"OwnerKey\" = \"8:_UNDEFINED\"\r\n\"MsmSig\" = \"8:_UNDEFINED\"\r\n}\r\n");
54             }
55             foreach (SetupDirectoryInfo folder in Folders)
56                 sb.Append(folder.CreateHierarchyString());
57 
58             return sb.ToString();
59         }
60 
61         #region 文字模板
62         private static string _defaultString = @" ""AlwaysCreate"" = ""11:FALSE""
63         ""Condition"" = ""8:""
64         ""Transitive"" = ""11:FALSE""
65         ""Folders"" 
66             { 
67                 $$  
68             }
69         }
70         ";
71         #endregion 
72 
73         /// <summary>
74         /// 生成vdproj文件的文件夹字符串
75         /// </summary>
76         /// <returns></returns>
77         private string BuildCurrentFolderString()
78         {
79             StringBuilder sb = new StringBuilder();
80             sb.AppendFormat("\r\n\"{{9EF0B969-E518-4E46-987F-47570745A589}}:{0}\" \r\n", GUID_2);
81             sb.AppendFormat("{{\r\n\"Name\" = \"8:{0}\" \r\n",Name);
82             sb.AppendFormat("\"Property\" = \"8:{0}\" \r\n ", Property);
83             sb.Append(_defaultString);
84             return sb.ToString();
85         }
86     }
复制代码

 

  这两个实体类主要存储着文件和文件夹的信息,还提供了生成当前文件或文件夹对象的字符串的方法。对于SetupDirectoryInfo类里面还提供三个方法,是生成当前目录及子目录的所有文件夹字符串,当前目录及子目录所有文件的字符串的方法。

此外还需要两个工具类一个是用于GUID的生成

复制代码
1     class GUIDCreater
2     {
3         public static string CreateGUID2()
4         {
5             string result = "_"+Guid.NewGuid().ToString().Replace("-","").ToUpper();
6             return result;
7         }
8     }
复制代码

  还有对特殊字符的处理,经实践发现,如果文件或文件名存在着一些特殊字符(暂时发现美元符号‘$’)会使得正则处理的时候出错。于是先把那些特殊字符转换一下,等到正则处理完再把它还原成特殊字符。存储特殊字符和暂代字符串是用一个Dictionary。

复制代码
 1     class SpecialCharacter
 2     {
 3         private static Dictionary<string,string> innerDictory;
 4         private static Dictionary<string, string> InnerDictory
 5         {
 6             get 
 7             {
 8                 if (innerDictory == null)
 9                     innerDictory = new Dictionary<string, string>();
10                 return innerDictory;
11             }
12         }
13 
14         public static void AddCharacter(string value)
15         {
16             if (value.Length != 1)
17                 throw new Exception("value' length too long");
18             if (!InnerDictory.ContainsKey(value))
19                 InnerDictory.Add(value, GUIDCreater.CreateGUID2());
20         }
21 
22         public static void ClearRecord()
23         {
24             InnerDictory.Clear();
25         }
26 
27         /// <summary>
28         /// 将特殊的字符转换成其他字符串
29         /// </summary>
30         /// <param name="content"></param>
31         /// <returns></returns>
32         public static string ChangeSpecialCharacter(string content)
33         {
34             foreach (KeyValuePair<string,string> iDic in InnerDictory)
35             {
36                 if (content.Contains(iDic.Key))
37                     content=content.Replace(iDic.Key,iDic.Value);
38             }
39             return content;
40         }
41 
42         /// <summary>
43         /// 将转换后的字符串还原成原来的特殊字符
44         /// </summary>
45         /// <param name="content"></param>
46         /// <returns></returns>
47         public static string RecoverSpecialCharacter(string content)
48         {
49             foreach (KeyValuePair<string,string> iDic in InnerDictory)
50             {
51                 if (content.Contains(iDic.Value))
52                     content=content.Replace(iDic.Value,iDic.Key);
53             }
54             return content;
55         }
56     }
复制代码

 

然后就是完成导入任务的类了,其中下面这个方法则是导入的方法

复制代码
 1  public void ImportDirectory(string path,string vdproj, ImportType type)
 2         {
 3             Initial();//一些导入前的操作,这里实际上是给特殊字符的列表中添加特殊字符
 4             SetupDirectoryInfo dirInfo= CreateDirecotryTree(path);//分析给定目录下所有的子文件夹和文件
 5             string strFiles =SpecialCharacter.ChangeSpecialCharacter( dirInfo.CreateFilesString());//生成所有文件字符串
 6             string strFolders = SpecialCharacter.ChangeSpecialCharacter( dirInfo.CreateFoldersString());//生成所有文件夹字符串
 7             string strHierarchy = SpecialCharacter.ChangeSpecialCharacter( dirInfo.CreateHierarchyString());//生成所有Hierachy字符串
 8             string vdprojContent=SpecialCharacter.ChangeSpecialCharacter( File.ReadAllText(vdproj,Encoding.UTF8));//读取vdproj文件内容
 9             File.Copy(vdproj, vdproj + ".bak",true);//备份vdproj文件10 
11        //判断当前对“应用程序程序文件夹”的内容是追加还是覆盖
12             if (type == ImportType.Append)
13                vdprojContent=SpecialCharacter.RecoverSpecialCharacter( AppendContent(vdprojContent,strHierarchy, strFiles, strFolders));
14             else
15                vdprojContent=SpecialCharacter.RecoverSpecialCharacter( OverWriteContent(vdprojContent,strHierarchy, strFiles, strFolders));
16             File.WriteAllText(vdproj, vdprojContent,Encoding.UTF8); //保存更改后的vdproj文件
17             Finish();//清除特殊字符列表的内容
18         }
复制代码

 

这个类的其他方法就不一一列举了,在博文地步会附上整份源码。为了让操作方便一点,我自己还做了一个图形界面。

  好像做了这个导入器,是很笨的一个做法,估计解决这个文件结构难题的办法多的是,本来我用VS来打包,没用其他的工具,也已经很笨了。我有个搭档就跟我说,可以把那堆难缠的文件夹弄一个压缩包,在安装的时候解压就行了。喝喝!但是我没用他的那种方案。

  最近好像没时间写博文了,有空就写一下吧!我还是想更新我的博客的。

 完整源码
1     public class SetupImporter
  2     {
  3         #region Regex
  4         private static string _regFilesInner = @"(?<=""File""\r\n\s*{)[^{}]*(((?'Open'{)[^{}]*)+((?'-Open'})[^{}]*)+)*(?(Open)(?!))(?=})";
  5         private static string _regFoldersInner = @"(?<=""{3C67513D-01DD-4637-8A68-80971EB9504F}:_\w*""[\r\n\s{""#\w=:\[\]\\]*""Folders""\r\n\s*{)[^{}]*(((?'Open'{)[^{}]*)+((?'-Open'})[^{}]*)+)*(?(Open)(?!))(?=})";
  6         private static string _regHierachyInner = @"(?<=""Hierarchy""\r\n\s*{)[^{}]*(((?'Open'{)[^{}]*)+((?'-Open'})[^{}]*)+)*(?(Open)(?!))(?=})";
  7 
  8         private static string _regFilesOuter = @"""File""\r\n\s*{[^{}]*(((?'Open'{)[^{}]*)+((?'-Open'})[^{}]*)+)*(?(Open)(?!))}";
  9         private static string _regFoldersOuter = @"""{3C67513D-01DD-4637-8A68-80971EB9504F}:_\w*""[\r\n\s{""#\w=:\[\]\\]*""Folders""\r\n\s*{[^{}]*(((?'Open'{)[^{}]*)+((?'-Open'})[^{}]*)+)*(?(Open)(?!))}\r\n\s*}";
 10         private static string _regHierachyOuter = @"""Hierarchy""\r\n\s*{[^{}]*(((?'Open'{)[^{}]*)+((?'-Open'})[^{}]*)+)*(?(Open)(?!))}";
 11         #endregion
 12 
 13         public void ImportDirectory(string path,string vdproj, ImportType type)
 14         {
 15             Initial();
 16             SetupDirectoryInfo dirInfo= CreateDirecotryTree(path);
 17             string strFiles =SpecialCharacter.ChangeSpecialCharacter( dirInfo.CreateFilesString());
 18             string strFolders = SpecialCharacter.ChangeSpecialCharacter( dirInfo.CreateFoldersString());
 19             string strHierarchy = SpecialCharacter.ChangeSpecialCharacter( dirInfo.CreateHierarchyString());
 20             string vdprojContent=SpecialCharacter.ChangeSpecialCharacter( File.ReadAllText(vdproj,Encoding.UTF8));
 21             File.Copy(vdproj, vdproj + ".bak",true);
 22 
 23             if (type == ImportType.Append)
 24                vdprojContent=SpecialCharacter.RecoverSpecialCharacter( AppendContent(vdprojContent,strHierarchy, strFiles, strFolders));
 25             else
 26                vdprojContent=SpecialCharacter.RecoverSpecialCharacter( OverWriteContent(vdprojContent,strHierarchy, strFiles, strFolders));
 27             File.WriteAllText(vdproj, vdprojContent,Encoding.UTF8);
 28             Finish();
 29         }
 30 
 31         private SetupDirectoryInfo CreateDirecotryTree(string path)
 32         {
 33             DirectoryInfo root = new DirectoryInfo(path);
 34 
 35             SetupDirectoryInfo dir = new SetupDirectoryInfo();
 36             dir.Name = root.Name;
 37             dir.GUID_2 = GUIDCreater.CreateGUID2();
 38             dir.Property = GUIDCreater.CreateGUID2();
 39 
 40             FileInfo[] files = root.GetFiles();
 41             List<SetupFileInfo> fileList = new List<SetupFileInfo>(files.Length);
 42             SetupFileInfo fileItem = null;
 43             foreach (FileInfo file in files)
 44             {
 45                 fileItem = new SetupFileInfo();
 46 
 47                 fileItem.GUID_2 = GUIDCreater.CreateGUID2();
 48                 fileItem.SourcePath = file.FullName.Replace("\\","\\\\");
 49                 fileItem.TargetName = file.Name;
 50                 fileItem.Folder = dir.GUID_2;
 51                 
 52                 fileList.Add(fileItem);
 53             }
 54             dir.Files = fileList;
 55 
 56             DirectoryInfo[] dirs = root.GetDirectories();
 57             List<SetupDirectoryInfo> folderList = new List<SetupDirectoryInfo>(dirs.Length);
 58             SetupDirectoryInfo dirItem = null;
 59             foreach (DirectoryInfo item in dirs)
 60             {
 61                 dirItem = CreateDirecotryTree(item.FullName);
 62                 folderList.Add(dirItem);
 63             }
 64             dir.Folders = folderList;
 65 
 66             return dir;
 67         }
 68 
 69         private string OverWriteContent(string vdprojContent, string strHierarchy, string strFiles, string strFolders)
 70         {
 71            vdprojContent = Regex.Replace(vdprojContent, _regFilesInner, strFiles );
 72            vdprojContent = Regex.Replace(vdprojContent, _regFoldersInner,  strFolders );
 73            vdprojContent = Regex.Replace(vdprojContent, _regHierachyInner,  strHierarchy );
 74 
 75            return vdprojContent;
 76         }
 77 
 78         private string AppendContent(string vdprojContent,string strHierarchy, string strFiles, string strFolders)
 79         {
 80             string macthFiles = Regex.Match(vdprojContent, _regFilesInner).Value;
 81             string macthFolders = Regex.Match(vdprojContent, _regFoldersInner).Value;
 82             string matchHierachy = Regex.Match(vdprojContent, _regHierachyInner).Value;
 83             strFiles += macthFiles;
 84             strFolders += macthFolders;
 85             strHierarchy += matchHierachy;
 86 
 87             vdprojContent = OverWriteContent(vdprojContent,strHierarchy, strFiles, strFolders);
 88             return vdprojContent;
 89         }
 90 
 91         private void Initial()
 92         {
 93             SpecialCharacter.AddCharacter("$");
 94         }
 95 
 96         private void Finish()
 97         {
 98             SpecialCharacter.ClearRecord();
 99         }
100     }
101 
102     public enum ImportType
103     {
104         Append,
105         OverWrite
106     }
107 
108     class SetupFileInfo
109     {
110         public string GUID_1
111         { get { return "1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE"; } }
112         public string SourcePath { get; set; }
113         public string TargetName { get; set; }
114         public string Folder { get; set; }
115         public string GUID_2 { get; set; }
116 
117         #region 文字模板
118         private static string _defaultString = @" ""Condition "" =  ""8:"" 
119             ""Transitive"" = ""11:FALSE"" 
120             ""Vital"" = ""11:TRUE"" 
121             ""ReadOnly"" = ""11:FALSE"" 
122             ""Hidden"" = ""11:FALSE"" 
123             ""System"" = ""11:FALSE"" 
124             ""Permanent"" = ""11:FALSE"" 
125             ""SharedLegacy"" = ""11:FALSE"" 
126             ""PackageAs"" = ""3:1"" 
127             ""Register"" = ""3:1"" 
128             ""Exclude"" = ""11:FALSE"" 
129             ""IsDependency"" = ""11:FALSE"" 
130             ""IsolateTo"" = ""8:"" 
131             }
132             ";
133         #endregion
134 
135         /// <summary>
136         /// 生成vdproj的文件的字符串
137         /// </summary>
138         /// <returns></returns>
139         public string CreateFileItemInfo()
140         {
141             StringBuilder sb = new StringBuilder();
142             sb.AppendFormat("\r\n\"{{{0}}}:{1}\" \r\n", GUID_1, GUID_2);
143             sb.AppendFormat("{{\r\n \"SourcePath\" = \"8:{0}\" \r\n", SourcePath);
144             sb.AppendFormat("\"TargetName\" = \"8:{0}\" \r\n", TargetName);
145             sb.AppendLine("\"Tag\" = \"8:\"");
146             sb.AppendFormat("\"Folder\" = \"8:{0}\" \r\n",Folder);
147             sb.AppendLine(_defaultString);
148 
149             return sb.ToString();
150         }
151     }
152 
153     class SetupDirectoryInfo
154     {
155         public static string GUID_1
156         { get { return "9EF0B969-E518-4E46-987F-47570745A589"; } }
157         public string GUID_2 { get; set; }
158         public string Property { get; set; }
159         public string Name { get; set; }
160         public List<SetupDirectoryInfo> Folders { get; set; }
161         public List<SetupFileInfo> Files { get; set; }
162 
163         /// <summary>
164         /// 生成当前目录和子目录的所有文件的字符串
165         /// </summary>
166         /// <returns></returns>
167         internal string CreateFilesString()
168         {
169             StringBuilder sb = new StringBuilder();
170 
171             foreach (SetupFileInfo item in Files)
172                 sb.Append(item.CreateFileItemInfo());
173 
174             foreach (SetupDirectoryInfo item in Folders)
175                 sb.Append(item.CreateFilesString());
176 
177             return sb.ToString();
178         }
179         
180         /// <summary>
181         /// 生成当前目录及子目录的文件夹字符串
182         /// </summary>
183         /// <returns></returns>
184         internal string CreateFoldersString()
185         {
186             StringBuilder sb = new StringBuilder();
187             foreach (SetupDirectoryInfo item in Folders)
188                 sb.Append(item.CreateFoldersString());
189 
190             string result = BuildCurrentFolderString().Replace("$$", sb.ToString());
191             return result;
192         }
193 
194         /// <summary>
195         /// 供解决方案资源管理器用
196         /// </summary>
197         /// <returns></returns>
198         internal string CreateHierarchyString()
199         {
200             StringBuilder sb = new StringBuilder(); 
201             foreach (SetupFileInfo file in Files)
202             {
203                 sb.AppendLine("\r\n\"Entry\"\r\n{");
204                 sb.AppendFormat("\"MsmKey\" = \"8:{0}\"\r\n",file.GUID_2);
205                 sb.AppendLine("\"OwnerKey\" = \"8:_UNDEFINED\"\r\n\"MsmSig\" = \"8:_UNDEFINED\"\r\n}\r\n");
206             }
207             foreach (SetupDirectoryInfo folder in Folders)
208                 sb.Append(folder.CreateHierarchyString());
209 
210             return sb.ToString();
211         }
212 
213         #region 文字模板
214         private static string _defaultString = @" ""AlwaysCreate"" = ""11:FALSE""
215         ""Condition"" = ""8:""
216         ""Transitive"" = ""11:FALSE""
217         ""Folders"" 
218             { 
219                 $$  
220             }
221         }
222         ";
223         #endregion 
224 
225         /// <summary>
226         /// 生成vdproj文件的文件夹字符串
227         /// </summary>
228         /// <returns></returns>
229         private string BuildCurrentFolderString()
230         {
231             StringBuilder sb = new StringBuilder();
232             sb.AppendFormat("\r\n\"{{9EF0B969-E518-4E46-987F-47570745A589}}:{0}\" \r\n", GUID_2);
233             sb.AppendFormat("{{\r\n\"Name\" = \"8:{0}\" \r\n",Name);
234             sb.AppendFormat("\"Property\" = \"8:{0}\" \r\n ", Property);
235             sb.Append(_defaultString);
236             return sb.ToString();
237         }
238     }
239 
240     class GUIDCreater
241     {
242         public static string CreateGUID2()
243         {
244             string result = "_"+Guid.NewGuid().ToString().Replace("-","").ToUpper();
245             return result;
246         }
247     }
248 
249     class SpecialCharacter
250     {
251         private static Dictionary<string,string> innerDictory;
252         private static Dictionary<string, string> InnerDictory
253         {
254             get 
255             {
256                 if (innerDictory == null)
257                     innerDictory = new Dictionary<string, string>();
258                 return innerDictory;
259             }
260         }
261 
262         public static void AddCharacter(string value)
263         {
264             if (value.Length != 1)
265                 throw new Exception("value' length too long");
266             if (!InnerDictory.ContainsKey(value))
267                 InnerDictory.Add(value, GUIDCreater.CreateGUID2());
268         }
269 
270         public static void ClearRecord()
271         {
272             InnerDictory.Clear();
273         }
274 
275         /// <summary>
276         /// 将特殊的字符转换成其他字符串
277         /// </summary>
278         /// <param name="content"></param>
279         /// <returns></returns>
280         public static string ChangeSpecialCharacter(string content)
281         {
282             foreach (KeyValuePair<string,string> iDic in InnerDictory)
283             {
284                 if (content.Contains(iDic.Key))
285                     content=content.Replace(iDic.Key,iDic.Value);
286             }
287             return content;
288         }
289 
290         /// <summary>
291         /// 将转换后的字符串还原成原来的特殊字符
292         /// </summary>
293         /// <param name="content"></param>
294         /// <returns></returns>
295         public static string RecoverSpecialCharacter(string content)
296         {
297             foreach (KeyValuePair<string,string> iDic in InnerDictory)
298             {
299                 if (content.Contains(iDic.Value))
300                     content=content.Replace(iDic.Value,iDic.Key);
301             }
302             return content;
303         }
304     }

 

 
 
分类: C#
posted on 2013-07-21 14:31  HackerVirus  阅读(233)  评论(0编辑  收藏  举报