TFS 2010使用自定义输出构建Sharepoint 2010解决方案 [英] TFS 2010 Building Sharepoint 2010 Solution With Custom Outputs

查看:119
本文介绍了TFS 2010使用自定义输出构建Sharepoint 2010解决方案的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对此SO帖子有一个非常相似的问题: TFS Build 2010-自定义二进制位置和SharePoint WSP .没有明确的答案,但是唯一提供的答案似乎是要走的路.

我正在构建多个解决方案,并且需要将解决方案和项目放置到自己的文件夹中.这导致生成输出更改为我正在使用的模板中的MSBuild调用.我已经使用了一段时间,没有任何问题.

最近,开发人员抱怨说在我们的日常构建中没有生成.wsp文件.我调查了一下,发现了前面提到的SO帖子.

我已按照说明进行操作,但现在出现了新错误:

C:\ Program Files(x86)\ MSBuild \ Microsoft \ VisualStudio \ v10.0 \ SharePointTools \ Microsoft.VisualStudio.SharePoint.targets(411):未找到方法:'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生成计算机上安装了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,网络上都没有信息!

更新 我拆开了构建服务器上的Microsoft.VisualStudio.SharePoint.dll.没有PathUtils类或命名空间.我可能对此文件有错误的版本吗?我怎么能检测到呢?我是否应该在构建服务器上安装Sharepoint SDK.它已经安装了Sharepoint 2010.

更新2
我检查了GAC.显示Microsoft.VisualStudio.Sharepoint程序集.但是,只有在运行x64版本的Visual Studio命令提示符时才能找到它.当我运行正常的组件时,我得不到组装.我假设这是因为Sharepoint程序集是64位.据我所知,TFS设置为64位.这是我的问题吗?

解决方案

我找到了解决此问题的方法.我认为没有人遇到过这种情况,因此我怀疑是否会有正确的"解决方案.我将在此处发布为允许将.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 任务/类.

第二步 知道要看的地方后,我将任务反编译了.我使用了Telerik的JustDecompile,但在Reflector中也想出了相同的代码.

我可以清楚地看到这一行:

if (PathUtils.HasIllegalDeploymentPathCharacters(str2))

哪个是错误的.

第三步 我最终决定使用 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 目录中(再次备份原始目标文件)./p>

这使我能够通过TFS 2010使用自定义输出构建由SharePoint解决方案生成的wsp文件!

我将此网站用作资源: http://blogs.like10.com/2011/08/04/team-build-2010-customized-output-directories-sharepoint-2010-wsps/

(我可能已经将另外一个或两个站点用作资源,但目前可以在浏览器历史记录中找到它们.)

您的行驶里程可能会有所不同,但是请告知我是否有人遇到过类似的问题并且能够以非黑客入侵"的方式修复它.

更新
整个问题似乎来自我管理的原始TFS安装.最近,我将我们的团队转移到了正确的TFS服务器(2012)上,该服务器具有全新的操作系统安装和新的数据库服务器.在我迁移数据库并在TFS中运行升级任务后,我能够进行一些小的构建编辑以使我的构建可以在2012年使用,而我第二次没有遇到此问题.我相信,因为原始的2010 TFS在转换后的 dev 机器上,所以导致了此问题.

I have a very similar question to this SO post: TFS Build 2010 - Custom Binary Location and SharePoint WSP. There's no marked answer, but the only answer provided seemed to be the path to go.

I'm building several solutions and need the solutions and projects to be placed into their own folders. This lead to the build output change to the MSBuild call in the template that I'm using. I've been using this for sometime without any issues.

Recently a developer complained that the .wsp files were not being generated in our daily build. I looked into this and came across the fore mentioned SO post.

I followed the instructions and now have a new error:

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)'.

I've looked at this line (411) in the targets file:

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

The PackageFiles target is defined:

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

I checked the GAC and didn't see it there so I added it. The TFS 2010 Build machine has Visual Studio 2010 and Sharepoint 2010 installed on it. I don't think I need to do anything other than changing this task:

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

So that OutDir points to $(TargetDir).

Am I missing something as to why I'm getting this error where now a method cannot be found? This error is very exasperating as there is no information on the web regardless of the Google Fu employed!

Update I've pulled apart the Microsoft.VisualStudio.SharePoint.dll that's on the build server. There is no PathUtils class or Namespace. Could I possibly have a bad version of this file? How can I detect this? Should I install the Sharepoint SDK on the build server. It already has Sharepoint 2010 installed on it.

Update 2
I checked the GAC. The Microsoft.VisualStudio.Sharepoint assembly shows up. However, I can only find it when I'm running the x64 version of the Visual Studio Command Prompt. When I run the normal one I get no assembly back. I'm assuming that is because the Sharepoint assembly is 64 bit. As far as I know TFS is setup to be 64bit. Is this going to be my problem?

解决方案

I found a solution to this issue. I don't think anyone has ever encountered this so I'm doubtful there will be a "correct" solution. I will post here what I have done to allow my .wsp files to build in the solution.

By all means, please post an answer (or comment on either this answer or the original question) if you think there is a better solution or if my manner of solving the problem is not up to par.

I will explain this in steps that I came up with to solve the problem.

First Step The task PackageFiles was giving me the issue. This task was unable to find a method to invoke. Looking at the file C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\SharePointTools\Microsoft.VisualStudio.SharePoint.targets we can find this on line 56:

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

I know knew where to look for the PackageFiles task/class.

Step Two After knowing where to look I decompiled the task. I used Telerik's JustDecompile but I also came up with the same code in Reflector.

I could clearly see the line:

if (PathUtils.HasIllegalDeploymentPathCharacters(str2))

Which was erroring.

Step Three I ended up deciding that the PathUtils.HasIllegalDeploymentPathCharacters method was just there as a safety check. I could recreate this task in my own custom library and then insert it into a custom targets file.

Here was the class I came up with:

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;
    }
  }
}

Since most of the classes and methods are marked as internal I had to make use reflection to get the type and method needed to actually build the cab/wsp files. This is done in the method: GetStaticMethod

Step Four If you read over the decompiled code and my custom version of the class you'll notice the Strings class. It appears to be a resource accessor class. I decided that I'd just decompile that code as well and use it in my solution that makes the custom task instead of reflecting every time I wanted to access a string resource. This file ended up not being a straight decompile as it has a line this.GetType().Assembly it uses to get the current assembly containing the resources. This works fine within the original assembly but causes a problem in this custom assembly.

The original line:

internal Strings()
{
    this.resources = new ResourceManager("Strings", this.GetType().Assembly);
}

This line had to be changed to:

Assembly sharepointTasksAss = Assembly.Load("Microsoft.VisualStudio.SharePoint.Tasks");
this.resources = new ResourceManager("Strings", sharepointTasksAss);

Step Five After I had a custom build task that mimics the original I needed to now place that into the targets file. I then backed up the original targets file and made a custom one replacing the UsingTask section like this:

  <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" />

This made the task point to my DLL which contained the custom task. Specifically, this line:

<UsingTask AssemblyFile="C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\SharePointTools\SharepointTaskLibrary.dll" TaskName="PackageFiles" />

FINALLY
I dropped the compiled DLL and edited targets file into the C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\SharePointTools directory (again backing up the original targets file).

This allowed me to build via TFS 2010 with custom outputs the wsp files generated by the SharePoint solutions!

I used this site as a resource: http://blogs.like10.com/2011/08/04/team-build-2010-customized-output-directories-sharepoint-2010-wsps/

(I may have used another one or two sites as a resource, but I can find them in the browser history at the moment).

Your mileage may vary, but please let me know if anyone has this similar issue and is able to fix it in a non "hacked" way.

UPDATE
This whole issue seems to have came from the original TFS install I was administering. I recently moved our team to a proper TFS server (2012) with a completely fresh OS install and a new database server. Once I migrated the databases over and ran the upgrade tasks in TFS I was able to do some small build edits to make my build work with 2012 and I did not encounter this issue a second time. I believe that because the original 2010 TFS was on a converted dev machine it caused this problem.

这篇关于TFS 2010使用自定义输出构建Sharepoint 2010解决方案的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆