2010年6月23日,星期三

功能升级(第1部分)- 基本的s

在本系列文章中:

  1. 功能升级(第1部分)– 基本的s (this article)
  2. 功能升级(第2部分)–一个样本玩
  3. 功能升级(第3部分)–引入SPFeatureUpgrade套件
  4. 功能升级(第4部分)– advanced scenarios
  5. 功能升级(第5部分)–使用PowerShell升级功能

在最近的文章中’ve谈到了 版本控制可升级性 SharePoint 2010中的功能框架。I’我们最近在会议演讲(SharePoint Evolutions)中以及即将出版的Real World SharePoint 2010书中的一章中都讨论了此主题。–但是我也想在这里涵盖一定程度,因为我’请注意,并不是每个人都来参加谈判或会买这本书。我也想介绍一个工具’已在Codeplex上发布,如果您决定使用功能升级,这可能会很有用-下一篇文章中会对此进行更多介绍。

什么时候使用功能升级?

功能升级在以下情况下很有用(尽管可能还会更多!):

  • 对现有网站集或网站或其中的某些内容进行更改– for example:
    • 对现有项目进行更改,例如向内容类型/列表添加新列
    • 向现有网站添加新元素,例如新清单
    • 任何涉及使用API​​对网站进行操作的更改,例如使用代码修改许多站点的导航设置
  • 向现有功能中添加新功能,而不是创建新功能–也许是因为’最合乎逻辑的分解
  • 在此期间,某些功能将被多次升级的地方’的生命周期,可能是在变更未部署到每个站点或不在不同时间部署的情况下

如果你’重新修改或扩展使用“功能”开发的功能(跨多个站点或仅一个站点),那么“功能升级”可能是展开更改的好工具。这部分是由于新 QueryFeatures() API中的方法,它们提供了一个方便的集合来迭代以应用更改。当更改本身也通过代码实现时,过去的开发人员可能会将其实现放在代码中。 功能激活 事件,然后确保停用/重新激活功能-但这是随身携带的,因为您可能在其中有其他代码,这些代码从不打算重新运行。功能升级旨在解决此类问题。

功能升级是什么样的?

Microsoft向功能框架添加了一些新的XML,以支持功能升级。创建功能的新版本时,这可能涉及:

  • 增加现有功能的版本号(这对于功能升级是必需的)
  • 添加一些新的XML为功能定义新项目
  • 编写一些代码以在新代码中执行 功能升级 功能接收器中的事件
  • 上述所有的

这里’s是一个升级功能的示例,突出了一些可能性:

<?xml version="1.0" encoding="utf-8" ?>
<Feature xmlns="http://schemas.microsoft.com/sharepoint/" ="1.0.0.0">
  <UpgradeActions>
    <版本范围 BeginVersion="0.0.0.0" 最终版本="0.9.9.9">
      <ApplyElementManifests>
        <ElementManifest Location="SomeFunctionality_Iteration2\Elements.xml" />
      </ApplyElementManifests>
      
      <AddContentTypeField ContentTypeId="0x010073f25e2ac37846bb8e884770fb7307c7"
          FieldId="{536DC46C-DC26-4DB0-A97C-7C21E4362A85}" 下推式="TRUE"/>
      <AddContentTypeField ContentTypeId="0x010073f25e2ac37846bb8e884770fb7307c7"
          FieldId="{4E7A6719-011A-47EA-B983-A4941D688CA6}" 下推式="TRUE"/>
 
      <CustomUpgradeAction 名称="UpdateSomething">
        <Parameters>
          <Parameter 名称="PassSomeValue">This is a string</Parameter>
        </Parameters>
      </CustomUpgradeAction>
    </版本范围>
</Feature>

[边注] 请注意,以上XML实际上是完整feature.xml文件的子集–使用功能升级时,有必要退出Visual Studio 2010中的功能设计器并直接编辑XML文件(老式的方法!)。这样做时最好的选择是让VS 合并 您使用其管理的XML进行的更改。打包WSP时,由VS管理的XML与您的自定义XML合并– if you could 这个 XML隔离位(您可以’t,因为您永远不需要),这可能看起来像这样:

<Feature Title="Some functionality" Id="cae1f65d-0365-42e9-9907-356c7983e902" Scope="Site">
  <ElementManifests>
    <ElementManifest Location="SomeFunctionality\Elements.xml" />
    <ElementManifest Location="SomeMoreFunctionality\Elements.xml" />
  </ElementManifests>
</Feature>

Essentially Visual Studio will still manage our 元件manifests, but any XML around Feature upgrade needs to be edited by hand. Walking through the box containing the main XML, we can 看到:

  • 该功能有一个 属性(to be incremented each time the Feature is upgraded)
  • A 版本范围 元件defining the upgrade steps to process for a particular upgrade i.e. when an existing Feature 实例BeginVersion最终版本 使用更新的功能升级 定义
  • 一个 ApplyElementManifests 元件– 这个 is used to add new elements to an existing Feature. When the Feature is upgraded, any items (e.g. 内容类型, modules etc.) will be provisioned according to the 元件manifest(s)
  • AddContentTypeField 元件–对于将字段添加到现有内容类型的常见任务(这是非常常见的升级方案),这是一种便捷的机制。注意 下推式 属性–这是非常有用的,因为它可以完成将站点内容类型的更改推到站点内所有列表内容类型(因此,所有列表)的工作,而无需任何代码。
  • CustomUpgradeAction 元件–这使开发人员可以指向一些要运行的代码以执行升级操作。鉴于您可能需要在升级中进行大量操作,因此通常需要这种方法。在‘pointing’,实际上代码将永远是 功能升级 方法在接收器中,但在 名称 属性is passed to 这个 method to identify which code to run (along with any parameters). Hence your 功能升级 方法可能包含 开关 语句,如果要与上述XML相匹配,它将看起来像这样:
    public override void 功能升级(SPFeatureReceiverProperties properties, string upgradeActionName, System.Collections.Generic.IDictionary<string, string> parameters)
    {
        SPWeb parentWeb = (SPWeb)properties.Feature.Parent;
     
        开关 (upgradeActionName)
        {
            case "UpdateSomething":
                string someValue = parameters["PassSomeValue"];
                // do some stuff.. 
                break;
            default:
                break;
        }
    }

In addition to these possibilities there is one further declarative 元件– 地图文件. 地图文件 允许您指向未自定义文件的位置,这将从字面上更新数据库中的指针。您在其中的确切方案’d想使用它(而不是简单地部署原始文件的更新版本)不幸地逃避了我的小小的想法–我能想到的唯一一件事就是,如果它允许以DelegateControl之类的方式在不同的范围(例如Web)上进行重新指向,那将非常有用。一世’我无法验证这一点,因为我无法 地图文件 工作,我认识的其他人(@jthake)也没有尝试过。那好吧。

退一步看看这些工具,它’很容易想到,如果你不这样做’碰巧将字段添加到内容类型,那么实际上’重新看代码。然而 ApplyElementManifests 通常是某些情况下所需的全部一组新字段+一种新的内容类型+一种新的发布页面布局。

笔记

这些是一些‘fundamental’ things to know – I’在以后的文章中将讨论一些更高级的方面:

  • 功能升级不会自动发生(包括停用/重新激活功能时)! 升级功能的唯一方法是致电 SPFeature.Upgrade(), 通常与 QueryFeatures() 方法。我的工具’接下来要讨论的是一个自定义应用程序页面,可以帮助您完成本部分–请注意,没有STSADM命令,PowerShell cmdlet或用户界面可以立即执行此操作。
  • 版本范围 元件, BeginVersion 具有包容性,但 最终版本 不是。换句话说,如果当前版本号等于或大于,Feature实例将被升级。 BeginVersion ,且少于  最终版本。
  • 升级说明按文件中定义的顺序执行。
  • 如果功能没有 属性,版本为0.0.0.0。
  • 启用日志记录可以帮助诊断任何问题。 在ULS设置中,‘SharePoint基础’类别,请将以下子类别设置为“详细”以查看更多信息:
    • 功能基础架构
    • 领域
    • 一般

概要

SharePoint 2010引入了附加的生命周期管理功能,包括版本和升级功能。有一些声明性元素,例如 ApplyElementManifestsAddContentTypeField, 但是使用 CustomUpgradeAction 元件allows you to shell out to code where necessary. The only way to actually perform upgrade on a Feature once it has been updated is to call SPFeature.Upgrade() 在应该升级的功能的每个实例(例如,每个网站)上– new QueryFeatures() 方法可帮助您找到可以升级的功能实例。一世’已经编写了一个自定义应用程序页面,该页面有助于管理此过程,将在下一次讨论。

27条评论:

杰里米·塔克(Jeremy Thake)说过...

感谢您在这方面的帮助,我've uploaded my 演示网络广播 来自澳大利亚会议的所有内容,您的读者可能会觉得很有趣。

匿名 said...

Powershell功能升级是可能的:

$ site = get-spsite("http://your-site")
$ site.Features ["feature-guid"].upgrade($false)

克里斯·奥'Brien说过...

@Elgolfin,

好的,我们可以使用PowerShell中的任何.Net API进行任何操作:)

但是,如果没有cmdlet可以提供的抽象,则对于某些场景而言,这可能比在单个网站集中升级单个网站范围内的Feature实例的示例更加真实,从而使情况变得混乱。如果我们想升级所有可以升级的功能实例,我们'd然后需要额外的脚本来运行QueryFeatures()等。因此,我绝对认为'需要使用PS升级功能"one script command" way.

如果我们同意你的观点'逻辑上的结论,这是否意味着Microsoft编写他们提供的500多个PS cmdlet毫无意义? :)

克里斯。

创业人群说过...

克里斯,你好
如果这可行的话,就像在Moss 2007上一样,我们一直在为Sharepoint专门针对基于WCM的项目进行企业部署。

我们的项目分为多个阶段,其中在第一阶段,我们有一些功能正在上线,而第二阶段是平衡功能。我需要了解在为第一阶段功能进行修复和增强时,是否可以使用相同的框架。
我需要一些指导,因为我该如何升级
母版页
版面页面
网站栏,
内容类型,
工作流程和工作流程关联,
信息路径表格
共享点列表,库,
应用程序页面(在布局文件夹中部署),
自定义CSS
javascript文件
控制模板(用于用户控件),
自定义字段类型,
Web部件(OOTB和自定义),
网站定义,
针对CQWP的样式库中的自定义XSL,
布局图像
预览母版页的图像,
页面上添加了多个Web部件,
webpart添加到现有页面。

以上所有升级,更改和全新部署。

内存

克里斯·奥'Brien说过...

@内存,

I'我不是100%清楚你的意思'要求,但是首先要说的是功能升级框架是SharePoint 2010而不是2007的一部分。但是,仍然可以升级您在2007年列出的工件,'只是没有那么方便或明显的方法。有些工件可以在文件系统上被覆盖(例如,作为功能部件部署的母版页/布局),而其他工件则需要代码进行升级(例如,内容类型)。

我在SharePoint Evolutions会议上的ALM演示中详细介绍了(几乎列出了所有工件),我的资料夹在此处提供 http://www.milwaukeeticketsblog.com/2010/05/sharepoint-2010-alm-my-slide-decks-from.html

HTH,

克里斯。

路加说过...

在底部的段落中"什么时候使用功能升级?"您提到了FeatureActivating部分。这个对吗?我印象中代码将在FeatureUpgrading下执行?您提到了两次,所以我只想澄清一下它实际上是在激活还是升级下运行的。

谢谢,

路加说过...

克里斯,

抱歉,在我先前的评论中,我误以为我的困惑所在。我的问题是关于名为CustomUpgradeAction元素的项目符号点,它位于FeatureUpgrading的代码上方。你说"该代码将始终是接收器中的FeatureActivating方法。"这是令我困惑的部分。应该'这是FeatureUpgrading方法吗?

克里斯·奥'Brien说过...

@卢克,

是的,这是一个错字,您绝对正确,我的意思是FeatureUpgrading事件。实际上,前几天我也注意到了这一点,但忘了纠正它。

文字现已更新。非常感谢!

克里斯。

拉加布 said...

太棒了..这样的优雅写作风格。谢谢克里斯

乔纳森·B said...

迄今为止有关升级的最佳文章。非常感谢!请提出一个问题:如果我只是想向我不拥有的功能中定义的现有内容类型添加新的网站栏,该怎么办?在这种情况下,我无法升级功能,因为我没有't own it.

克里斯·奥'Brien说过...

@乔纳森

好问题。我其实在那里'没有什么阻止您将AddContentTypeField与您不拥有的功能提供的内容类型一起使用的。记住你们'要做的就是指定内容类型的ID和要添加的字段的ID。

如果我'错误的后备方法是使用命令式选项(即在FeatureUpgrading事件中编写代码)并以这种方式添加字段。

HTH,

克里斯。

匿名 said...

克里斯,你好



感谢这个过多的系列,它'我很清楚。



在进行一些功能升级时,我偶然发现了以下问题:

I'具有1.0.0.0版的功能。我创建了到2.0.0,0的升级,并通过STSADM更新了软件包。然后,我调用了.Upgrade方法。但是,升级过程中出现错误,因此升级失败。
我更正了Visual Studio中的错误,更新了服务器上的程序包,并尝试再次升级功能,但随后发现该功能已具有2.0.0.0版。

升级失败后,是否有一种方法可以完全还原功能升级?

预先感谢您的答复!

最好的祝福,

马腾

克里斯·奥'Brien说过...

@Maarten,

It'这是一个很好的问题,在本系列的第3部分中也提出了一个问题。为了方便起见'我对那个评论者说的是:

那'这是一个很大的问题-在开发功能升级XML /代码时,确实确实需要测试*多个*功能升级迭代。你不能专门"rollback"进行这样的升级,但是通过将版本号还原为要使用的真实版本(例如1.0.0.1)并“重新安装”功能(即通过撤回/重新部署WSP而不是升级),最终结果是该功能将与当前功能内容一起安装在该版本上。然后,您可以将其用作功能的版本,以升级到其他环境。换句话说,SharePoint不会维护功能的历史版本's state.

希望有道理。

克里斯。

匿名 said...

克里斯,你好

感谢您的回答,对不起我的英语不好。过多当然不是正确的词,它当然应该是广泛的(或更好的可表达词):-)

匿名 said...

克里斯,

完成升级过程。可以在功能中添加可视化Web部件吗?我收到位于的解决方案文件错误""似乎不是解决方案的有效升级""。这两个解决方案必须具有相同的资源类型(全局或Web应用程序范围)。它是最初在全球范围内部署的站点功能。我能够运行自定义操作,但是一旦添加Web部件,便无法升级。谢谢。

克里斯·奥'Brien说过...

@匿名,

在添加Web部件(无论是否可见)时,'已将WSP的范围从全局更改为Web应用程序范围。您不能升级WSP来部署此更改,必须将其撤消并重新部署。

注意确保您知道这将产生的效果。例如,是否会自动激活任何功能而导致不良的副作用?在此过程中,我经常快照开发环境。

HTH,

克里斯。

莫罗莫多说过...

克里斯,你好

我一直在阅读有关SharePoint功能更新的最佳做法,并发现您的系列非常有帮助。
我认为您可能希望获得有关MapFile的反馈。我没有'曾亲自使用过,但在MS初始出版物中发现了以下信息:

'MapFile — Allows you to map an uncustomised file to a different location on the front-end Web server. You can use the FromPath 和 ToPath 在 tributes to rename a file in a Feature (for example, , but you can also use 地图文件to move a file. In 这个 case, the FromPath 和 ToPath 在 tributes specify paths that are relative to the TEMPLATE directory. For example, if a Feature named "MyFeature"在.gif文件中安装了"Gifs"目录(例如,%ProgramFiles%\ Common Files \ Microsoft Shared \ Web服务器扩展\ 14 \ TEMPLATE \ FEATURES \ MyFeature \ 动态图 \ basketball.gif),并且在版本2中,您希望从“Gifs” to “Images”,则可用于移动文件。'

看到:
http://msdn.microsoft.com/en-us/library/ie/ee537575.aspx

问候,
加雷斯。

克里斯·奥'Brien说过...

@mrmorodo,

是的,我也读过。无论如何,请多加评论。

干杯,

克里斯。

k说过...

在第一个功能代码中,应该最后一个结尾但只有一行吗?

克里斯·奥'Brien说过...

@jkps,

是的,就是你're right, it's missing a closing </UpgradeActions>元件。抱歉,发现的很好:)

克里斯。

山姆 said...

优秀的克里斯。

我遇到了不确定如何解决的问题。在关注您的帖子之后,我的项目一开始的升级就很好。然后最近,无论我做什么,我都遇到了不再触发FeatureUpgrading事件的地方。我的服务器场已修补到SP1,您是否知道CU中的FeatureUpgrading修复了所有错误's after SP1?

谢谢

克里斯·奥'Brien说过...

@山姆

嗯,我'我不知道任何变化。当您使用QueryFeatures()方法之一测试需要升级的功能实例时,是否列出了您的功能?如果不是,您在增加版本号和部署WSP方面是否有其他不同的做法?

谢谢,

克里斯。

山姆 said...

谢谢您回复我。

是的,在我通过PowerShell执行Update-SPSolution之后,我可以看到该功能显示其已准备好进行升级(通过执行QueryFeatures()并使用"管理功能升级"在您的SPFeatureUpgrade套件中)。

在我的FeatureUpgrading事件中,我只是从内容类型中删除了ReadOnly(易于测试)。

我的初始版本是1.0.0.0,因此我将其递增到版本2.0.0.0,并且在UpgradeActions的VersionRange中。

我使用您的升级"管理功能升级"。我可以看到系统进行了升级,因为我运行PowerShell脚本向我显示了升级前的版本和升级后的版本,并且可以看到它从1.0.0.0递增到2.0.0.0。但是,当我向FeatureUpgrading事件添加调试断点时,它永远不会被击中。当我打开诊断日志时,我不知道'在SharePoint日志中看不到该事件被触发(我也看到其他事件如FeatureInstalling和FeatureActivated被触发)。

正如我所说的,它起初是有效的。然后,我向CustomUpgrades添加了更多内容以添加更多列。之后,我无法使事件再次触发。因此,这使我认为也许我遇到了SharePoint中的问题或错误。很奇怪。

克里斯·奥'Brien说过...

@山姆

也许要尝试的一件事是在干净的状态下重新安装/激活Feauture in dev。看看您是否再次遇到同一问题将很有趣。

不然我可以't say I'我之前见过'm afraid.

祝一切顺利,

克里斯。

未知说过...

如何处理功能中仅代码更改的情况。例如,我有一个类,其中某个功能中包含一些辅助方法,许多其他功能都使用该类。我现在可以想象有两种情况。我添加了一个新的助手方法。在这种情况下,我只会更改AssemblyFileVersion,而不会更改AssemblyVersion。我是否只需要用新功能文件进行Update-SPSolution即可替换GAC中的文件?我想我不´在这种情况下,可以为任何实例调用feature.upgrade。

第二种情况是,某些现有功能已更改,但是依赖于此功能的功能仍然可以使用。在这种情况下,我需要GAC中有两个版本的程序集。我认为在这种情况下,Mapfile指令会帮助我吗?

卡纳比兰说过...

克里斯,您好,本文是否仍然适用于SharePoint 2013内部部署?

克里斯·奥'Brien说过...

@Kannabiran,

是的,功能升级框架在SP2013中与SP2010相同。

干杯,

克里斯。