2

問題: 実行可能ファイルをビルドするプロセスがあります。セットアップ/デプロイ プロジェクトのビルドを実行する前に、セットアップ/デプロイ プロジェクトの 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 チーム ビルドに関する優れたチュートリアル。ここでは、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 に答える