问题: 有一个构建我们的可执行文件的过程。在运行setup / deploy项目的构建之前,我构建了需要包含在setup / deploy项目的FileSystem / Common Documents文件夹中的文件。如果文件名始终创建为相同的文件名,这很简单;但是,我有一个案例,我无法预先确定文件名,因为该过程可以并且将在每次连续运行时创建一个唯一的文件名。
问题: 如何以编程方式将文件添加到FileSystem / Common Documents文件夹?
我的研究: 我已查看自定义操作但不确定如何引用setup / deploy项目的FileSystem,以便我可以添加这些文件。
进一步详情 作为我们日常构建过程的一部分,我们创建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);
}
答案 0 :(得分:1)
您需要将所需信息添加到.V?PROJ(就像在C ++中一样,您有文件扩展名VDPROJ)。要添加到安装程序文件的“文件”部分中的必需信息。这不是一个单步过程,请通过安装程序项目文件(VDPROJ文件)并理解它。