zoukankan      html  css  js  c++  java
  • 一个打包文件导入器

    一个打包文件导入器

    不光是敲代码,最近连打包也做了,各种各样的打包要解释:给仪器打包,吃饭时帮同事打包饭菜,给生成好的程序打包。由于这里是博客园,仪器打包和饭菜打包不能说太多,不然有移出首页的危险。之前写了两篇关于安装包制作的博文了,这回继续写与安装包相关的。尽管现在有不少的打包工具,但是还用着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("
    "{{{0}}}:{1}" 
    ", GUID_1, GUID_2);
    36             sb.AppendFormat("{{
     "SourcePath" = "8:{0}" 
    ", SourcePath);
    37             sb.AppendFormat(""TargetName" = "8:{0}" 
    ", TargetName);
    38             sb.AppendLine(""Tag" = "8:"");
    39             sb.AppendFormat(""Folder" = "8:{0}" 
    ",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("
    "Entry"
    {");
    52                 sb.AppendFormat(""MsmKey" = "8:{0}"
    ",file.GUID_2);
    53                 sb.AppendLine(""OwnerKey" = "8:_UNDEFINED"
    "MsmSig" = "8:_UNDEFINED"
    }
    ");
    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("
    "{{9EF0B969-E518-4E46-987F-47570745A589}}:{0}" 
    ", GUID_2);
    81             sb.AppendFormat("{{
    "Name" = "8:{0}" 
    ",Name);
    82             sb.AppendFormat(""Property" = "8:{0}" 
     ", 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""
    s*{)[^{}]*(((?'Open'{)[^{}]*)+((?'-Open'})[^{}]*)+)*(?(Open)(?!))(?=})";
      5         private static string _regFoldersInner = @"(?<=""{3C67513D-01DD-4637-8A68-80971EB9504F}:_w*""[
    s{""#w=:[]\]*""Folders""
    s*{)[^{}]*(((?'Open'{)[^{}]*)+((?'-Open'})[^{}]*)+)*(?(Open)(?!))(?=})";
      6         private static string _regHierachyInner = @"(?<=""Hierarchy""
    s*{)[^{}]*(((?'Open'{)[^{}]*)+((?'-Open'})[^{}]*)+)*(?(Open)(?!))(?=})";
      7 
      8         private static string _regFilesOuter = @"""File""
    s*{[^{}]*(((?'Open'{)[^{}]*)+((?'-Open'})[^{}]*)+)*(?(Open)(?!))}";
      9         private static string _regFoldersOuter = @"""{3C67513D-01DD-4637-8A68-80971EB9504F}:_w*""[
    s{""#w=:[]\]*""Folders""
    s*{[^{}]*(((?'Open'{)[^{}]*)+((?'-Open'})[^{}]*)+)*(?(Open)(?!))}
    s*}";
     10         private static string _regHierachyOuter = @"""Hierarchy""
    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("
    "{{{0}}}:{1}" 
    ", GUID_1, GUID_2);
    143             sb.AppendFormat("{{
     "SourcePath" = "8:{0}" 
    ", SourcePath);
    144             sb.AppendFormat(""TargetName" = "8:{0}" 
    ", TargetName);
    145             sb.AppendLine(""Tag" = "8:"");
    146             sb.AppendFormat(""Folder" = "8:{0}" 
    ",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("
    "Entry"
    {");
    204                 sb.AppendFormat(""MsmKey" = "8:{0}"
    ",file.GUID_2);
    205                 sb.AppendLine(""OwnerKey" = "8:_UNDEFINED"
    "MsmSig" = "8:_UNDEFINED"
    }
    ");
    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("
    "{{9EF0B969-E518-4E46-987F-47570745A589}}:{0}" 
    ", GUID_2);
    233             sb.AppendFormat("{{
    "Name" = "8:{0}" 
    ",Name);
    234             sb.AppendFormat(""Property" = "8:{0}" 
     ", 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#
  • 相关阅读:
    ASIHTTPREQUEST 文档
    本地通知
    ASIHttpRequest 使用过程中,中文编码的问题
    讲讲最近自己的学习,谈谈未来的想法
    关于 ASP.NET MVC 4 如果管理用户
    [转贴]超级懒汉编写的基于.NET的微信SDK
    [转贴]实践:C++平台迁移以及如何用C#做C++包装层
    [转贴]Linq之动态查询
    [转贴]watin的一些例子
    [转贴]xcode帮助文档
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3203684.html
Copyright © 2011-2022 走看看