2012-05-25 4 views
0

У меня очень похожий вопрос на этот пост SO: TFS Build 2010 - Custom Binary Location and SharePoint WSP. Нет никакого заметного ответа, но единственным ответом, который, казалось, был путь.TFS 2010 Building Sharepoint 2010 Решение с пользовательскими выводами

Я создаю несколько решений и нуждаюсь в решениях и проектах, которые будут размещены в их собственных папках. Это приводит к изменению вывода сборки в вызов MSBuild в используемом шаблоне. Я использовал это когда-нибудь без каких-либо проблем.

Недавно разработчик жаловался, что файлы .wsp не генерируются в нашей ежедневной сборке. Я посмотрел на это и натолкнулся на передний план, упомянутый SO post.

Я следовал инструкциям и теперь новая ошибка:

C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\SharePointTools\Microsoft.VisualStudio.SharePoint.targets (411): Method not found: 'Boolean Microsoft.VisualStudio.SharePoint.PathUtils.HasIllegalDeploymentPathCharacters(System.String)'.

Я смотрел на этой линии (411) в файле мишени:

<PackageFiles LayoutPath="$(LayoutPath)%(EnumeratedFiles.Package)\" PackagePath="$(BasePackagePath)%(EnumeratedFiles.Package).$(PackageExtension)" /> 

PackageFiles целью является

<UsingTask AssemblyFile="Microsoft.VisualStudio.SharePoint.Tasks.dll" TaskName="PackageFiles" /> 

Я проверил GAC и не видел его там, поэтому Я добавил. На машине TFS 2010 Build установлены Visual Studio 2010 и Sharepoint 2010. Я не думаю, что мне нужно сделать что-нибудь другое, чем изменение этой задачи:

<CreateSharePointProjectService Configuration="$(Configuration)" 
           Platform="$(Platform)" 
           ProjectFile="$(MSBuildProjectFile)" 
           ProjectReferences="@(SharePointProjectReference)" 
           OutDir="$(TargetDir)"> 
    <Output PropertyName="ProjectService" TaskParameter="ProjectService" /> 
</CreateSharePointProjectService> 

, так что OUTDIR указывает на $ (TargetDir).

Я пропустил что-то относительно того, почему я получаю эту ошибку, где теперь метод не может быть найден? Эта ошибка очень раздражает, поскольку в Интернете нет информации, независимо от того, как Google Fu работает!

Update Я растаскивают на Microsoft.VisualStudio.SharePoint.dll, что на сервере сборки. Нет класса PathUtils или пространства имен. Возможно, у меня есть плохая версия этого файла? Как я могу это обнаружить? Должен ли я установить SDK Sharepoint на сервер сборки. На нем уже установлен Sharepoint 2010.

Обновление 2
Я проверил GAC. Появится сборка Microsoft.VisualStudio.Sharepoint. Тем не менее, я могу найти его только при запуске x64 версии командной строки Visual Studio. Когда я запускаю обычный, я не получаю сборку назад. Я предполагаю, что это потому, что сборка Sharepoint имеет 64 бит. Насколько я знаю, TFS настроен на 64 бит. Это будет моя проблема?

ответ

0

Я нашел решение этой проблемы. Я не думаю, что кто-либо когда-либо сталкивался с этим, поэтому я сомневаюсь, что будет «правильное» решение. Я опубликую здесь, что я сделал, чтобы мои .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" /> 

I знал, где искать PackageFiles task/class.

Шаг 2 Узнав, где искать, я декомпилировал задачу. Я использовал JustDecompile Telerik, но я также придумал тот же код в Reflector.

я мог ясно видеть линию:

if (PathUtils.HasIllegalDeploymentPathCharacters(str2)) 

Который был erroring.

Шаг третий я в конечном итоге решить, что 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

Шаг четвертый Если вы читали над декомпилированный код и мой заказ версия класса вы заметите 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); 

Шаг Пять После того как я имел задание на заказ сборки, который имитирует оригинал мне нужно прямо сейчас поместите это в файл целей.Я тогда резервное копирование оригинального файла целевых показателей и сделал заменяющего раздел 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 (снова резервное копирование исходного файла цели).

Это позволило мне создать через TFS 2010 с пользовательскими выводами файлы wsp, созданные решениями SharePoint!

Я использовал этот сайт как ресурс: http://blogs.like10.com/2011/08/04/team-build-2010-customized-output-directories-sharepoint-2010-wsps/

(я мог бы использовать еще один или два сайта в качестве ресурса, но я могу найти их в истории браузера на данный момент).

Ваш пробег может отличаться, но, пожалуйста, дайте мне знать, есть ли у кого-нибудь подобная проблема и он может исправить это не «взломанным» способом.

UPDATE
Вся эта проблема, похоже, пришла из оригинального TFS установки я администрирование. Недавно я перевел нашу команду на правильный сервер TFS (2012) с полностью новой установкой ОС и новым сервером базы данных. После того, как я переместил базы данных и выполнил задачи обновления в TFS, я смог сделать некоторые небольшие изменения, чтобы сделать мою работу с 2012 годом, и я не сталкивался с этой проблемой во второй раз. Я считаю, что, поскольку оригинальная TFS 2010 была на преобразованном dev машине, это вызвало эту проблему.

0

Вы пропускаете сборку «Microsoft.VisualStudio.SharePoint.Designers.Models.dll»

следующих узлов должны быть скопированы в GAC системы сборки:

Microsoft.VisualStudio.SharePoint.Designers.Models.dll Microsoft.VisualStudio.SharePoint.Designers.Models.Features.dll Microsoft.VisualStudio.SharePoint.Designers.Models.Packages.dll Microsoft.VisualStudio.SharePoint.dll

Пожалуйста, обратитесь к в следующей статье для получения дополнительной информации о необходимых сборках:

http://msdn.microsoft.com/en-us/ff622991.aspx

с уважением,

Уэс Макдональд

+0

Привет, Уэс, я собирался ответить на ваш адрес электронной почты, когда увидел, что у меня есть обновление на SO! Я использовал эту ссылку, которую вы опубликовали в моем первом раунде попыток исправления. В нем упоминается, что Sharepoint установлен в системе сборки или запускает сценарий powershell на dev-машине, чтобы получить необходимые файлы, чтобы добавить их в GAC сборки. У нас уже есть Sharepoint (и SDK Sharepoint), установленный на сервере сборки. Я также проверил, что все эти DLL находятся в GAC. Вот почему этот вопрос оставил меня настолько расстроенным! –

2

Метод PathUtils.HasIllegalDeploymentPathCharacters присутствует в версии 10.0.40219.1 из Microsoft.VisualStudio.SharePoint.Designers.Models.dll, а не в версии 10.0.30319.1 (где я видел эту ошибку).

+0

Недавно я перенес наш экземпляр TFS 2010 от одной машины к экземпляру TFS 2012 на другой машине, и я не видел, чтобы эта проблема снова возникала. Я считаю, что причина этого в том, что поле TFS, из которого возникла эта проблема, - это псевдо-ящик, преобразованный в хост-файл TFS. Теперь, когда у меня есть правильный сервер TFS, нет проблем. –

+0

Это было точное решение и причина моей ошибки. В моем случае на TFS 2015 переносятся старые рабочие процессы с версией. –