문제점 : 실행 파일을 빌드하는 프로세스가 있습니다. setup/deploy 프로젝트 빌드를 실행하기 전에 setup/deploy 프로젝트의 FileSystem/Common Documents 폴더에 포함되어야하는 파일을 빌드합니다. 파일 이름이 항상 동일한 파일 이름으로 작성되는 경우에는 매우 간단합니다. 그러나 프로세스가 각각의 연속 실행시 고유 한 파일 이름을 만들 수 있기 때문에 파일 이름을 미리 결정할 수없는 경우가 있습니다..NET의 ProjectSystem에 프로그램 적으로 파일을 추가 프로젝트 설치
질문 : 프로그래밍 방식으로 파일 시스템/공통 문서 폴더에 파일을 추가하려면 어떻게합니까?
내 연구 : 나는 사용자 지정 작업으로 보였지만/설정의 파일 시스템을 참조 나는이 파일을 추가 할 수 있도록 프로젝트를 배포하는 방법을 확실 해요했다.
상세 정보는 우리의 일상 빌드 프로세스의 일환으로 , 우리는 * .cfs의 형태로 파일이 전날 다른 파일 이름을 가질 수 http://lucene.apache.org/ (루씬) 인덱스를 만들 수 있습니다. Visual Studio에서 vdproj 파일을 열지 않고 파일 시스템 편집기를 사용하여 파일 이름을 수동으로 바꾸기를 원하지 않기 때문에보다 자동화 된 접근 방식이 필요했습니다. 우리의 솔루션
는 솔루션으로서, 나는 TFS 팀 빌드에 http://www.ewaldhofman.nl/post/2011/04/06/Customize-Team-Build-2010-e28093-Part-16-Specify-the-relative-reference-path.aspx (에 발트 호프만의) 훌륭한 튜토리얼을 사용했다. 여기서는 체크 아웃 활동 및 체크인 활동을 복제하면서 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);
}
이것은 의미가 없습니다. 프로세스가 * after * 파일을 설치하면 매우 일반적입니다. 그러면 설치 프로그램에서 아무 것도 할 필요가 없습니다. –
@HansPassant 그는 빌드 과정 중에 파일을 만들어야하고 설치 프로젝트에 추가해야한다고 생각합니다. –
나는 그 일을 할 방법을 모르고 있습니다. 프로젝트 자체를 설치하기 전에 (즉, 단지 XML 일뿐입니다) 설치 프로세스를 수정해야합니다 (그래서 TFS 서버에 _clean_ 버전을 유지할 것입니다). –