2

问题: 有一个构建我们的可执行文件的过程。在运行 setup/deploy 项目的构建之前,我构建了需要包含在 setup/deploy 项目的 FileSystem/Common Documents 文件夹中的文件。如果文件名总是被创建为相同的文件名,这很简单;但是,我有一个无法预先确定文件名的情况,因为该过程可以并且将在每次连续运行时创建一个唯一的文件名。

问题: 如何以编程方式将文件添加到 FileSystem/Common Documents 文件夹?

我的研究: 我研究了自定义操作,但不确定如何引用设置/部署项目的文件系统,以便我可以添加这些文件。

更多细节 作为我们日常构建过程的一部分,我们创建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(Ewald Hofman 的)关于 TFS Team Build 的优秀教程。在此,我复制了他的签出活动和签入活动,同时添加了我自己的自定义活动,该活动打开 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);
    }

4

1 回答 1

1

您需要将所需信息添加到 .V?PROJ(如在 C++ 中,您有文件扩展名 VDPROJ)。需要添加到安装程序文件的文件部分的信息。这不是一个步骤的过程,请通过安装程序项目文件(VDPROJ 文件)并理解它。

于 2012-07-31T11:31:37.260 回答