2012-05-16 16 views
2

問題: 在生成我們的可執行文件的過程中。在運行setup/deploy項目的構建之前,我會構建需要包含在setup/deploy項目的FileSystem/Common Documents文件夾中的文件。在文件名始終以相同文件名創建的情況下,這非常簡單;但是,我有一種情況,我無法預先確定文件名,因爲進程可以並且會在每次連續運行時創建唯一的文件名。以編程方式將文件添加到.NET安裝項目中的文件系統

問題: 如何以編程方式將文件添加到FileSystem/Common Documents Folder?

我的研究: 我特地到自定義操作,但我不確定如何引用設置的文件系統/部署的項目,所以我可以添加這些文件。

進一步詳細 作爲我們每日構建過程的一部分,我們創建http://lucene.apache.org/(Lucene的)指標凡在* .cfs形式文件可以與上一交易日不同的文件名。由於我們不希望在Visual Studio中打開vdproj文件並使用文件系統編輯器手動替換文件名,因此我們需要更自動化的方法。

我們的解決方案 作爲一個解決方案,我用http://www.ewaldhofman.nl/post/2011/04/06/Customize-Team-Build-2010-e28093-Part-16-Specify-the-relative-reference-path.aspx(埃瓦爾德福滿)目前關於TFS團隊建設優秀教程。在這裏,我複製了他的簽出活動和簽入活動,同時添加了我自己的自定義活動,以打開vdproj文件並根據預先生成的Lucene索引文件名稱編輯文件。

代碼示例

 

    protected override void Execute(CodeActivityContext context) 
    { 

     string fileFullName = context.GetValue(this.FileFullName); 

     string dropFolder = context.GetValue(this.DropLocation); 

     string[] indexerNames = context.GetValue(this.LuceneIndexes); 

     try 
     { 
      //read the vdproj file into memory 
      string text = File.ReadAllText(fileFullName); 

      //for each lucene index folder 
      foreach (string index in indexerNames) 
      { 

       //traversing twice so that the lucene index and spell index can be handled 
       //these are subfolder names we use to segregate our normal lucene index from our spelling indexes. 
       foreach (string subFolderInLuceneIndex in new string[] { "en_US_9", "en_US_9_sp" }) 
       { 

        //retrieve all the files in folder \\[DropFolder]\[index]\[subFolderInLuceneIndex]\*.cfs 
        foreach (string file in Directory.GetFiles(System.IO.Path.Combine(dropFolder, index, subFolderInLuceneIndex), "*.cfs")) 
        { 
         FileInfo cfsFile = new FileInfo(file); 

         context.TrackBuildMessage(string.Format("Exiting file in lucene index directory: {0}", cfsFile.FullName)); 

         string fileNamePattern = ".+.cfs"; 

         string div = Dividor(4); 

         //matching pattern for sourcepath ie("SourcePath" = "8:\\\\...\\[index]\\[subFolderInLuceneIndex]\\_0.cfs") 
         string sourcePattern = string.Format("(\".+{1}{0}{2}{0}{3})", div, index, subFolderInLuceneIndex, fileNamePattern); 

         //matching pattern for targetname ie("TargetName" = "8:_0.cfs") 
         string targetPattern = string.Format("(\"TargetName\"\\s=\\s\"8:{0})", fileNamePattern); 

         StringBuilder sb = new StringBuilder(); 
         sb.Append(sourcePattern); 
         sb.Append("(.+\\r\\n.+)"); //carriage return between targetpattern and sourcepattern 
         sb.AppendFormat(targetPattern); 

         //(.+[index]\\\\[subFolderInLuceneIndex].+.cfs)(.+\r\n.+)(TargetName.+8:.+.cfs) 

         MatchCollection matches = Regex.Matches(text, sb.ToString(), RegexOptions.Multiline); 
         //if more than one match exists, a problem with the setup and deployment file exists 
         if (matches.Count != 1) 
         { 
          throw new Exception("There should exist one and only one match."); 

         } 
         else 
         { 

          foreach (Match match in matches) 
          { 
           string newText = text; 

           string existingPattern = match.Value; 

           if (match.Groups != null) 
           { 
            //if the value found using the match doesn't contain the filename, insert the filename 
            //into the text 
            if (!match.Value.Contains(cfsFile.Name)) 
            { 
             //matched by sourcePattern 
             string sourceValue = match.Groups[1].Value; 

             //matched by targetPattern 
             string targetNameValue = match.Groups[3].Value; 

             int idIndex = targetNameValue.IndexOf("8:") + 2; 

             //get the old *.cfs file name 
             string oldFileName = targetNameValue.Substring(idIndex, targetNameValue.Length - idIndex); 

             //replace old cfs file name with new cfs file name in the target pattern 
             string newTargetNameValue = Regex.Replace(targetNameValue, oldFileName, cfsFile.Name); 

             //replace old cfs file name with new cfs file name in the source pattern 
             string newSourceValue = Regex.Replace(sourceValue, oldFileName, cfsFile.Name); 

             //construct the new text that will be written to the file 
             StringBuilder newSb = new StringBuilder(); 
             newSb.Append(newSourceValue); 
             //account for the quote, carriage return and tabs. this ensures we maintain proper 
             //formatting for a vdproj file 
             newSb.Append("\"\r\n\t\t\t"); 
             newSb.AppendFormat(newTargetNameValue); 

             newText = Regex.Replace(text, sb.ToString(), newSb.ToString(), RegexOptions.Multiline); 

             File.WriteAllText(fileFullName, newText); 

             context.TrackBuildMessage(string.Format("Text {0} replaced with {1}.", oldFileName, cfsFile.Name)); 

            } 
            else 
            { 
             context.TrackBuildMessage("No change applied for current file."); 
            } 
           } 
          } 
         } 
        } 
       } 

      } 

     } 
     catch (Exception ex) 
     { 

      context.TrackBuildError(ex.ToString()); 

      throw ex; 
     } 
    } 
    private static string Dividor(int n) 
    { 
     return new String('\\', n); 
    } 
 
+0

這沒有任何意義。如果進程在*安裝後創建文件*,當然很常見,那麼您無需在安裝程序中爲此做任何事情。 –

+0

@HansPassant我猜他需要在構建過程中創建一些文件,並將它們添加到安裝項目中。 –

+0

我不知道有任何方法可以做到這一點。我會在你的過程中立即修改安裝項目(畢竟它只是XML),然後它將會被構建(所以你會在你的TFS服務器上保留一個_clean_版本)。 –

回答

1

您需要添加必要的信息,以.V?PROJ(像在C++中,你有文件擴展名VDPROJ)。必需的信息被添加到安裝程序文件的文件部分。這不是一個單獨的步驟,請通過安裝程序項目文件(VDPROJ文件)並理解它。

+0

對我描述的問題有兩個要求。 1.我需要以編程方式添加文件。 2.添加沒有預定名稱的文件。 VDPROJ文件被理解的級別沒有問題。 VDPROJ文件提供的靈活性是。簡單地說......在給定的技術中,並非所有的東西都是可能的。轉向Wix是解決方案。 – JDennis

相關問題