この問題の解決策を見つけました。誰もこれに遭遇したことはないと思うので、「正しい」解決策があるかどうかは疑わしいです。.wspファイルをソリューションに組み込むために行ったことをここに投稿します。
より良い解決策があると思われる場合、または問題を解決する私の方法が標準に達していない場合は、必ず回答を投稿してください(またはこの回答または元の質問にコメントしてください)。
問題を解決するために思いついた手順でこれを説明します。
最初のステップPackageFiles
タスクで問題が発生しました。このタスクは、呼び出すメソッドを見つけることができませんでした。ファイルC:\ Program Files(x86)\ MSBuild \ Microsoft \ VisualStudio \ v10.0 \ SharePointTools \ Microsoft.VisualStudio.SharePoint.targetsを見ると、56行目でこれを見つけることができます。
<UsingTask AssemblyFile="Microsoft.VisualStudio.SharePoint.Tasks.dll" TaskName="PackageFiles" />
PackageFilesタスク/クラスを探す場所を知っていました。
ステップ2
どこを見ればよいかを知った後、タスクを逆コンパイルしました。TelerikのJustDecompileを使用しましたが、Reflectorでも同じコードを思いつきました。
私ははっきりと線を見ることができました:
if (PathUtils.HasIllegalDeploymentPathCharacters(str2))
これはエラーでした。
ステップ3
結局、PathUtils.HasIllegalDeploymentPathCharactersメソッドが安全チェックとしてそこにあると判断しました。このタスクを自分のカスタムライブラリで再作成してから、カスタムターゲットファイルに挿入することができます。
これが私が思いついたクラスでした:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using Microsoft.VisualStudio.SharePoint.Tasks;
using Microsoft.Build.Framework;
namespace SharepointTaskLibrary
{
public class PackageFiles : BuildTask
{
[Required]
public ITaskItem LayoutPath
{
get;
set;
}
[Required]
public ITaskItem PackagePath
{
get;
set;
}
public PackageFiles()
{
}
protected override void OnCheckParameters()
{
if (this.LayoutPath == null)
{
throw new InvalidOperationException(Strings.GetString("LayoutPathNotSpecified"));
}
if (this.PackagePath == null)
{
throw new InvalidOperationException(Strings.GetString("PackagePathNotSpecified"));
}
}
protected override void OnExecute()
{
object[] objArray;
object[] objArray2;
object[] objArray3;
string metadata = this.LayoutPath.GetMetadata("FullPath");
string str1 = this.PackagePath.GetMetadata("FullPath");
Assembly sharepointTasksAss = Assembly.Load("Microsoft.VisualStudio.SharePoint.Tasks");
if (sharepointTasksAss != null)
base.Log.LogMessage(MessageImportance.High, "Found Tasks assembly!");
else
{
base.Log.LogError("Couldn't find the tasks assembly");
return;
}
if (!Directory.Exists(metadata))
{
base.Log.LogErrorFromResources("LayoutPathDoesNotExist", new object[] { metadata });
}
else
{
MethodInfo createCabMethod = GetStaticMethod(sharepointTasksAss, "Microsoft.VisualStudio.SharePoint.Tasks.Utilities.CabCreator", "CreateCabinet");
if (createCabMethod == null)
{
base.Log.LogError("the method could not be retrieved on type.");
return;
}
else
base.Log.LogMessage(MessageImportance.High, "Found method: " + createCabMethod.Name);
IEnumerable<string> strs = createCabMethod.Invoke(null, new object[] { metadata, str1 }) as IEnumerable<string>;
/*
* The following code would error in the original task.
*/
//foreach (string str2 in strs)
//{
// if (PathUtils.HasIllegalDeploymentPathCharacters(str2))
// {
// base.Log.LogWarningFromResources("FileNameContainsIllegalDeploymentPathCharacters", new object[] { str2 });
// }
//}
base.Log.LogMessage(MessageImportance.High, Strings.GetString("PackageCreatedSuccessfully"), new object[] { str1 });
}
Type codeMarkersType = null;
try
{
codeMarkersType = sharepointTasksAss.GetType("Microsoft.Internal.Performance.CodeMarkers", true);
}
catch (Exception e)
{
base.Log.LogErrorFromException(e, true);
}
if (codeMarkersType == null)
{
base.Log.LogError("Couldn't get the CodeMarkers class!");
return;
}
else
base.Log.LogMessage(MessageImportance.High, "Found the type: " + codeMarkersType.FullName);
/*
* This has yet to be added back in.
*/
//CodeMarkers.Instance.CodeMarker(CodeMarkerEvent.perfSharePointPackageWspPackageEnd);
}
private MethodInfo GetStaticMethod(Assembly assembly, string typeName, string methodName)
{
Type type = null;
try
{
type = assembly.GetType(typeName, true);
}
catch (Exception e)
{
base.Log.LogErrorFromException(e, true);
}
if (type == null)
{
base.Log.LogError("Couldn't get the type: " + typeName);
return null;
}
else
base.Log.LogMessage(MessageImportance.High, "Found the type: " + type.FullName);
MethodInfo methodInfo = type.GetMethod(methodName, BindingFlags.Static);
if (methodInfo == null)
{
MethodInfo[] methods = type.GetMethods().Union(type.GetMethods(BindingFlags.Static)).ToArray();
base.Log.LogWarning(string.Format("Wasn't able to find {0} directly. Searching through the static {1} method(s) on {2}", methodName, methods.Length, type.FullName));
foreach (MethodInfo info in methods)
{
if (info.Name == methodName && methodInfo == null)
methodInfo = info;
}
if (methodInfo == null)
{
MemberInfo[] members =
type.GetMembers().Union(type.GetMembers(BindingFlags.Static | BindingFlags.NonPublic)).Union(type.GetMembers(BindingFlags.NonPublic)).ToArray();
base.Log.LogWarning(string.Format("Wasn't able to find {0}. Searching through the {1} members(s) on {2}", methodName, methods.Length, type.FullName));
MemberInfo createCabMember = null;
foreach (MemberInfo member in members)
{
if (member.Name == methodName)
{
createCabMember = member;
break;
}
else
base.Log.LogMessage(MessageImportance.High, "Found member: " + member.Name);
}
if (createCabMember == null)
base.Log.LogError("Still wasn't able to find " + methodName + " in the members!");
}
}
return methodInfo;
}
}
}
ほとんどのクラスとメソッドは内部としてマークされているため、実際にcab/wspファイルをビルドするために必要なタイプとメソッドを取得するためにリフレクションを使用する必要がありました。これは、次のメソッドで実行されます:GetStaticMethod
ステップ4逆コンパイルされたコードとクラスのカスタムバージョンを読むと、 Stringsクラス
に気付くでしょう。リソースアクセサクラスのようです。そのコードも逆コンパイルして、文字列リソースにアクセスするたびに反映するのではなく、カスタムタスクを作成するソリューションで使用することにしました。このファイルにはthis.GetType()。Assemblyという行が含まれているため、このファイルは直接逆コンパイルされませんでした。リソースを含む現在のアセンブリを取得するために使用します。これは元のアセンブリ内では正常に機能しますが、このカスタムアセンブリで問題が発生します。
元の行:
internal Strings()
{
this.resources = new ResourceManager("Strings", this.GetType().Assembly);
}
この行は次のように変更する必要がありました。
Assembly sharepointTasksAss = Assembly.Load("Microsoft.VisualStudio.SharePoint.Tasks");
this.resources = new ResourceManager("Strings", sharepointTasksAss);
ステップ5
オリジナルを模倣するカスタムビルドタスクを実行した後、それをターゲットファイルに配置する必要がありました。次に、元のターゲットファイルをバックアップし、次のようにUsingTaskセクションを置き換えるカスタムファイルを作成しました。
<UsingTask AssemblyFile="Microsoft.VisualStudio.SharePoint.Tasks.dll" TaskName="CreateSharePointProjectService" />
<UsingTask AssemblyFile="Microsoft.VisualStudio.SharePoint.Tasks.dll" TaskName="EnumerateFiles" />
<UsingTask AssemblyFile="Microsoft.VisualStudio.SharePoint.Tasks.dll" TaskName="EnumerateFeature" />
<UsingTask AssemblyFile="Microsoft.VisualStudio.SharePoint.Tasks.dll" TaskName="EnumeratePackage" />
<UsingTask AssemblyFile="Microsoft.VisualStudio.SharePoint.Tasks.dll" TaskName="EnumerateProjectItem" />
<UsingTask AssemblyFile="Microsoft.VisualStudio.SharePoint.Tasks.dll" TaskName="LayoutFiles" />
<!-- The next task is a mimic of the one from the other assembly. I decompiled it and recreated it so it wouldn't error. LOL -->
<UsingTask AssemblyFile="C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\SharePointTools\SharepointTaskLibrary.dll" TaskName="PackageFiles" />
<UsingTask AssemblyFile="Microsoft.VisualStudio.SharePoint.Tasks.dll" TaskName="ResolveProjectMember" />
<UsingTask AssemblyFile="Microsoft.VisualStudio.SharePoint.Tasks.dll" TaskName="SetPackagingProperties" />
<UsingTask AssemblyFile="Microsoft.VisualStudio.SharePoint.Tasks.dll" TaskName="ValidatePackage" />
これはタスクは、カスタムタスクを含むDLLを指します。具体的には、この行:
<UsingTask AssemblyFile="C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\SharePointTools\SharepointTaskLibrary.dll" TaskName="PackageFiles" />
最後
に、コンパイルされたDLLと編集されたターゲットファイルをC:\ Program Files(x86)\ MSBuild \ Microsoft \ VisualStudio \ v10.0 \ SharePointToolsディレクトリにドロップしました(ここでも元のターゲットファイルをバックアップします)。
これにより、SharePointソリューションによって生成されたwspファイルをカスタム出力するTFS2010を介してビルドすることができました。
このサイトをリソースとして使用しました:http:
//blogs.like10.com/2011/08/04/team-build-2010-customized-output-directories-sharepoint-2010-wsps/
(リソースとして別の1つまたは2つのサイトを使用した可能性がありますが、現時点ではブラウザーの履歴でそれらを見つけることができます)。
あなたのマイレージは変わるかもしれませんが、誰かがこの同様の問題を抱えていて、「ハッキングされていない」方法でそれを修正できるかどうか私に知らせてください。
更新
この問題全体は、私が管理していた元のTFSインストールに起因しているようです。私は最近、完全に新しいOSインストールと新しいデータベースサーバーを備えた適切なTFSサーバー(2012)にチームを移動しました。データベースを移行してTFSでアップグレードタスクを実行すると、ビルドを2012で機能させるためにいくつかの小さなビルド編集を行うことができましたが、この問題は2度目に発生しませんでした。元の2010TFSは変換された開発マシン上にあったため、この問題が発生したと思います。