如何使用 Exchange 日历更新工具解决夏令时问题

文章翻译 文章翻译
文章编号: 930879 - 查看本文应用于的产品
重要说明:本文包含有关如何修改注册表的信息。修改注册表之前,一定要先对其进行备份,并且一定要知道在出现问题时如何还原注册表。有关如何备份、还原和修改注册表的更多信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
256986 Microsoft Windows 注册表说明
展开全部 | 关闭全部

本文内容

简介

2005 年 8 月 8 日,美国国会通过并由总统乔治·布什签署了 2005 年能源政策法案,从而使之成为一项法律。此法案规定了多项变更,其中包括修改下列地区中夏令时 (DST) 的开始日期和结束日期:
  • 除亚利桑那、夏威夷、波多黎各、美属维尔京群岛和美属萨摩亚之外的美国各州
注意
  • 加拿大全境都将实行新的 DST 开始日期和结束日期。
  • 亚利桑那州纳瓦霍族自治区实行 DST。
当此法律在 2007 年 3 月 11 日生效后,DST 将比传统时间提前三个星期开始,并将推迟一个星期结束。此更改通常称为 DST 2007。下表对此更改进行了描述。
收起该表格展开该表格
DST 开始日期DST 结束日期
新日期2007 年 3 月 11 日2007 年 11 月 4 日
以前的日期2007 年 4 月 1 日2007 年 10 月 28 日
根据 DST 2007 规定,时钟将于美国本地时间凌晨 02:00 进行更改。2007 年的关键日期如下:
  • 2007 年 3 月 11 日,时钟将从凌晨 01:59 向前调至凌晨 03:00。
  • 2007 年 11 月 4 日,时钟将从凌晨 01:59 向后调至凌晨 01:00。
在本文中,这些日期称为“DST 延长期”。

DST 更改适用于美国和加拿大。但是,该更改也会影响北美以外的个人和组织。在北美经营业务的组织以及在北美拥有客户、合作伙伴或供应商的组织将受到影响。此外,如果客户和系统与位于北美的系统或依赖日期和时间计算的系统进行交互或集成,则这些客户和系统也将受到影响。

本文重点介绍按照新 DST 规定更新 Microsoft Exchange Server 中存储的日历项目时应执行哪些操作。本文提供的解决方案会用到 Exchange 日历更新工具(“Exchange 工具”)。Exchange 工具依赖于 Microsoft Office Outlook 时区数据更新工具(“Outlook 工具”)。
有关 Outlook 工具的更多信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
931667 如何使用 Microsoft Office Outlook 时区数据更新工具解决 2007 年夏令时更改问题
有关如何为所有受影响的 Microsoft 产品做好准备以迎接 2007 年夏令时更改的更多信息,请访问下面的 Microsoft 网站:
http://www.microsoft.com/DST2007

关于 Exchange 工具

安装了 Microsoft Windows 的 DST 更新后,所有在 DST 更改期间发生的旧约会都将错误地显示为推迟一小时。不论定期约会还是单实例约会都是如此。这些约会必须经过更新才能在 Outlook、Outlook Web Access 以及基于 CDO 的应用程序中正确显示。

Outlook 提供了一个名为 Microsoft Office Outlook 时区数据更新工具的工具。用户使用此工具便可以对自己的日历进行更新。

注意:在 Microsoft Office Outlook 2007 中,该时区数据更新工具是内置的。但是,我们建议您使用该时区数据更新工具的单行版。
931667 如何使用 Microsoft Office Outlook 时区数据更新工具解决 2007 年夏令时更改问题
使用 Exchange 日历更新工具(“Exchange 工具”),可以避免当在大范围内向所有用户部署 Outlook 工具时出现的难题,并可确保每个用户都能正确运行该工具。

Microsoft 已创建一个虚拟机 (VM) 来帮助安装和使用 Exchange 日历更新工具。该虚拟机基于 Microsoft Windows Server 2003、Microsoft Office Outlook 2007、Microsoft Office Excel 2007 和 Microsoft Office Word 2007,并可在 Virtual PC 2004 和 Virtual Server 2005 R2 中运行。 有关更多信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
933185 Microsoft 提供了一个虚拟机来帮助您在 Exchange 组织中部署夏令时 2007 日历更新

关于 Exchange 工具的高级说明

Exchange 工具由两个单独的可执行文件组成。下表对这两个文件进行了描述。
收起该表格展开该表格
文件名说明
Msextmz.exe此可执行程序能够从运行 Exchange Server 的服务器上的邮箱中提取时区信息。此外,它还可以通过对每个指定的用户调用 Outlook 工具来更新指定的用户列表的邮箱日历。
Msextmzcfg.exe此可执行程序是一个配置工具,它将执行更新 Exchange Server 服务器时所涉及到的大多数步骤。

第 2 版 Exchange 工具

第 2 版 Exchange 日历更新工具发布于 2007 年 2 月 21 日。本文中提到 Exchange 工具时便是指它的第 2 个版本。如果您运行的是第 1 版 Exchange 工具,请将其卸载并安装第 2 版。第 2 版 Exchange 工具包括下列改进:
  • 当在更新模式下运行该工具时,第 2 版的性能比第 1 版快一倍。
  • 用户界面得到改进。
  • 需要经常重新启动客户端计算机的内存泄漏问题得到解决。
  • 将提取的时区映射到操作系统时区时使用的算法得到改进。

运行 Exchange 工具的风险和限制

在运行 Exchange 工具之前,需要考虑两个问题。下表列出了这些问题、它们对 IT 基础设施和用户的潜在影响及缓解策略。
收起该表格展开该表格
风险 影响缓解操作
存在大量的会议更新。服务器和网络性能降低。先更新一小批用户,以确定可能对服务器和网络性能造成的影响。如果负荷是中断性的,请在非高峰时段或专用维护时段运行该工具。
该工具运行时间过长。MSXTMZ.exe 以单线程模式运行。如果在更新模式下对几千个用户同时运行此文件,则 Exchange 工具可能需要数小时甚至几天才能完成。要加快所有邮箱的更新过程,请将用户分为多个批次,然后通过在单独的计算机上使用单独的 MSXTMZ.exe 实例来更新每批用户。

更新邮箱的选项

下表列出了五个选项,这些选项可用于将用户邮箱更新为使用 DST 2007 时区规则。
收起该表格展开该表格
选项优点缺点
向每个用户分发 Outlook 工具,然后指示用户更新他们自己的邮箱。此选项可避免运行 Exchange 工具时的风险和限制。难以保证所有用户都能够正确、及时地运行 Outlook 工具。未安装 Outlook 的用户将无法运行 Outlook 工具。为了减少用户疑问,还需要进行相应的培训。
对所有受影响的用户和服务器运行 Exchange 工具。此选项为用户提供了简化的体验。存在与运行 Exchange 工具关联的问题(如上表所述)。
运行 Exchange 工具并只更新定期约会。允许用户使用 Outlook 工具更新自己邮箱中的单实例约会。当单实例约会未得到正确更新时,风险较低。结合了运行 Outlook 工具与运行 Exchange 工具的缺点。
既不运行 Exchange 工具,也不运行 Outlook 工具。让用户检查他们的日历并根据需要重新预订约会。此选项可避免因运行 Exchange 工具而带来的问题。除非所有用户都重新预订所有受影响的约会,否则某些日历项目会在 DST 延长期间推迟一小时。为了减少用户疑问,还需要进行相应的培训。
向每个用户分发 Outlook 工具,然后指示用户更新他们自己的邮箱。接下来,使用 Exchange 工具的时区提取模式来确定用户是否正在运行 Outlook 工具。如果用户未运行 Outlook 工具,管理员便可以运行 Exchange 工具。此选项可降低因用户未及时运行该工具而产生的风险,并可避免运行 Exchange 工具所带来的问题。如果用户运行的是 Outlook 2007,则无法使用此选项。

如何安装 Exchange 工具

Exchange 日历更新工具以自解压缩的可执行文件 Msextmz.exe 的形式提供。

完成安装后,安装目录中的文件应包括下列文件:
  • Msextmz.exe
  • Msextmzcfg.exe
  • Msextmz.ini

    此文件是记录了 Msextmz.exe 使用的所有参数的主 .ini 文件。
  • Msextmzcfg.xml

    此文件是将 Outlook、CDO 和 Outlook Web Access 时区映射到操作系统时区的时区映射文件。

可以从 Microsoft 下载中心下载以下文件:
收起这个图片展开这个图片
下载
立即下载 Exchange 日历更新工具包。

Microsoft 已创建一个虚拟机来帮助安装和使用 Exchange 日历更新工具。该虚拟机基于 Microsoft Windows Server 2003、Microsoft Office Outlook 2007、Microsoft Office Excel 2007 和 Microsoft Office Word 2007,并可在 Virtual PC 2004 和 Virtual Server 2005 R2 中运行。

有关 Microsoft Exchange 日历更新工具的虚拟机的更多信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
933185 Microsoft 提供了一个虚拟机来帮助您在 Exchange 组织中部署夏令时 2007 日历更新
有关如何下载 Microsoft 支持文件的更多信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
119591 如何从联机服务获取 Microsoft 支持文件
Microsoft 已对此文件进行了病毒扫描。Microsoft 使用的是该文件发布时可以获得的最新病毒检测软件。该文件存储在安全性得到增强的服务器上,以帮助防止在未经授权的情况下对其进行任何更改。

Exchange 工具支持的语言

Exchange 工具只提供英文版,并且只在英文(美国)计算机上运行。

与 Exchange 工具兼容的 Exchange Server 版本

Exchange 工具可以更新下列 Exchange Server 版本上的邮箱:
  • Microsoft Exchange Server 2007 Enterprise Edition
  • Microsoft Exchange Server 2007
  • Microsoft Exchange Server 2007 Standard Edition
  • Microsoft Exchange Server 2003
  • Microsoft Exchange Server 2003 Enterprise Edition
  • Microsoft Exchange 2000 Server
  • Microsoft Exchange Server 2003 Standard Edition
  • Microsoft Exchange 2000 Server Enterprise Edition
  • Microsoft Exchange 2000 Server Standard Edition

Exchange 工具支持的操作系统

Exchange 工具将在下列操作系统上运行:
  • Microsoft Windows Server 2003
  • Microsoft Windows XP
  • Microsoft Windows 2000
不支持 Windows Vista。

运行 Exchange 工具之前的操作事项

安装更新

在运行 Exchange 工具之前,请确保已使用下列更新成功更新客户端和服务器计算机:
  1. 在客户端和服务器计算机上安装 Windows 夏令时更新。 有关如何更新运行 Windows 操作系统软件的计算机的更多信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
    931836 2007 年 2 月版 Microsoft Windows 操作系统累积时区更新
  2. 对于 Exchange 2003 SP2,请安装以下适于您的组织的更新:
    • 911829 当您在 Outlook Web Access 中尝试执行任何编辑任务或必须通过单击启用撰写框架时收到错误消息
    • 924334 当在 Exchange Server 2003 中的 Outlook Web Access 客户端上安装了 Internet Explorer 7.0 和 S/MIME 控件后,“撰写消息”窗体停止响应
    注意:此步骤可与步骤 1 同时完成。

验证系统要求

Exchange 工具必须在安装了 Microsoft Office Outlook 2003 或 Microsoft Office Outlook 2007 以及 Outlook 时区数据工具的计算机上运行。此外,客户端计算机上还必须安装 Microsoft .NET Framework 2.0 版。

Exchange 工具下载软件包中不包含 Outlook 和 Microsoft Office Outlook 时区数据更新工具。因此,必须单独安装它们。

注意:请勿将 Outlook 工具的安装程序包(名为 Tzmove.exe)与其实际的可执行文件(也名为 Tzmove.exe)相混淆。

要成功运行 Exchange 工具,不得在计算机上设置 PickLogonProfile 注册表值。或者,必须将此注册表值设置为 0。要确定此注册表值是否存在,请按照下列步骤操作。

警告:如果使用注册表编辑器或其他方法错误地修改了注册表,则可能会出现严重问题。这些问题可能需要重新安装操作系统才能解决。Microsoft 不能保证可以解决这些问题。修改注册表需要您自担风险。
  1. 依次单击“开始”和“运行”,键入 regedit,然后单击“确定”。
  2. 展开以下子项:
    HKEY_CURRENT_USER\Software\Microsoft\Exchange\client\options\
  3. 单击“options”,然后确定“PickLogonProfile”值是否存在。如果“PickLogonProfile”值存在且设置为 1,请将该值设置为 0。为此,请按照下列步骤操作:
    1. 右键单击“PickLogonProfile”,然后单击“修改”。
    2. 在“数值数据”框中,键入 0,然后单击“确定”。
Exchange 工具无法在运行 Exchange Server 或 Exchange 系统管理工具的计算机上运行。如果您尝试将 Exchange 工具安装在运行 Exchange Server 或 Exchange 系统管理工具的计算机上,您将收到以下错误消息:
Microsoft Exchange Calendar Update Tool cannot be installed with Microsoft Exchange.

如何手动配置和运行 Msextmz.exe

配置 Msextmz.ini 文件

必须正确配置 Msextmz.ini 文件才能使 Msextmz.exe 正确运行。我们建议您在修改 Msextmz.ini 文件之前先仔细阅读 Msextmz.ini 文件中的注释。

指定 Msextmz.exe 执行模式

Msextmz.exe 可在两种模式下运行。要指定执行模式,必须在 Msextmz.ini 文件中设置一些特定的参数。下面的列表描述了这三种模式,并说明如何在 Msextmz.ini 文件中配置这些模式。
  • 时区提取

    在此模式下,Msextmz.exe 将通过读取一组 MAPI 属性从每个邮箱中提取时区信息。

    Msextmz.exe 可以在用户的日历中检查由用户组织的定期约会,然后尝试确定该用户所在的时区。但是,此选项会占用大量资源。因此,默认情况下不启用此选项。要启用此选项,请在 Msextmz.ini 文件中设置 ReadCalendarTimezones 参数。

    Msextmz.exe 会将每个用户的时区信息记录在包含邮箱旧版 DN 列表的输出文件中。每个邮箱的旧版 DN 都包含下列类型的时区值:
    • Outlook Web Access 时区
    • CDO 时区
    • Outlook 时区
    • 定期会议时区
    该文件使用以下格式:
    User_DN<\TAB >CDO_Time_Zone<\TAB>Outlook Web Access_Time_Zone<\TAB>Outlook_Time_Zone<\TAB >Recurring_Meeting_Time_Zone<\CRLF>
    如果 Msextmz.exe 无法为上述四类时区中的任何一个提取时区信息,则将在错误文件中记录该邮箱的旧版 DN。

    要将用户仅映射到一个时区,必须将该输出文件导入到 Microsoft Excel 中。在 Excel 中,按照这些时区之一筛选用户列表。所用时区取决于您所在的环境。

    例如,如果大多数用户使用 BlackBerry 设备、Exchange 5.5 Outlook Web Access 或其他基于 CDO 的解决方案,请按 CDO 时区筛选该列表。如果大多数用户使用 Exchange Outlook Web Access,请按 Outlook Web Access 时区筛选该列表。如果大多数用户不属于上述任何一种情况,请按定期会议时区筛选该列表。

    要在时区提取模式下运行该工具,请按照下列步骤配置 .ini 文件:
    • 将 CommandLine 参数保留为取消注释状态。
    • 设置 OutputFile 参数。
    • 设置 ErrorFile 参数。
    • 设置 ServerDN 参数。
    • 设置 Profile 参数。
    • 设置 LogFile 参数。
    • 将 ExportTimezones 参数设置为 1。
    • 注释禁止该 .ini 文件中的剩余参数。
  • 更新

    在此模式下,Msextmz.exe 将更新输入文件中指定的所有邮箱。该输入文件应采用以下格式:
    User_DN<\TAB>Server_Friendly_Name<\TAB>OS_Time Zone_Registry_Key<\CRLF>
    一个客户端上只能运行 Msextmz.exe 的一个实例。但是,Msextmz.exe 可以同时在多个客户端上运行。

    要在此模式下运行 Msextmz.exe,必须按照下列步骤配置 Msextmz.ini 文件:
    • 确保 CommandLine 参数已被取消注释并指向 Tzmove.exe 的正确位置。
    • 设置 InputFile 参数。
    • 注释禁止 OutputFile 参数。
    • 设置 ErrorFile 参数。
    • 设置 ServerDN 参数。
    • 设置 LogFile 参数。
    • 设置 LogDirectory 参数。
    • 注释禁止 ExportTimezones 参数。
    • 取消注释剩余参数。
    在更新模式下,Msextmz.exe 可以接受包含不同 Exchange 服务器上的用户的输入文件。该 .ini 设置要求提供 Exchange 服务器的 DN。在此情况下,您只需在 Exchange 组织中指定 Exchange 服务器的服务器 DN 即可。

    要仅更新定期约会,请使用下面的值配置 CommandLine 参数:
    tzmove.exe /q /onlyrecurring
    要对定期约会和单实例约会都进行更新,请使用默认的 CommandLine 值。

配置 Msextmz.exe 的权限

运行 Msextmz.exe 所需的权限取决于所用的执行模式。下表列出了每个执行模式所需的权限。
收起该表格展开该表格
执行模式权限
时区提取Exchange 只读管理员
运行 Msextmz.exe 的计算机的本地管理员
更新对所有邮箱都具有完全邮箱访问和代理发送权限的域用户
运行 Msextmz.exe 的计算机的本地管理员

“授予邮箱权限”脚本

您可以使用示例 GrantMailboxPermission.vbs 脚本向域用户授予对所有邮箱的完全邮箱访问和代理发送权限。

此脚本只能由 Exchange 管理员在运行 Exchange 2000 Server 或 Exchange Server 2003 的计算机上运行。在运行 Exchange Server 2007 的计算机上无法运行此脚本。但是,您可以使用 Exchange 命令行管理程序授予必需的权限。

此 VBS 脚本的代码在“参考”部分中提供。下表描述了可以运行此脚本的两种模式。
收起该表格展开该表格
模式命令行说明
添加CScript GrantMailboxPermission.vbs –add Domain_Name\User_Name File_NameDomain_Name\User_Name 授予对输入文件中所列用户邮箱的完全邮箱访问和代理发送权限。该输入文件必须是一个包含用户邮箱旧版 DN 的文本文件,且各个邮箱之间用 CRLF 分隔。

该脚本会生成一个 GrantMailboxPermission.log 文件。此文件记录了经过处理的各个邮箱。该日志文件的第一行是已被授予访问权限的 Domain_Name\User_Name 用户。请勿删除此文件。在删除模式下还会用到此文件。

如果向用户明确分配了“拒绝”访问权限,则该脚本会在一个名为“GrantMailboxPermission.err”的文件中记录该信息,但不会授予或更改该权限。

如果用户是已分配“拒绝”访问权限的安全组的成员,则该脚本将授予完全邮箱访问和代理发送权限。但是,该用户将无法登录到邮箱中。所有错误都将记录在 GrantMailboxPermission.err 文件中。
删除CScript GrantMailboxPermission.vbs –removeDomain_Name\User_Name 删除对 GrantMailboxPermission.log 文件中所列邮箱的完全邮箱访问和代理发送权限。Domain_Name\User_Name 在 GrantMailboxPermission.log 文件中指定。
注意:当在运行 Exchange Server 的计算机上运行该脚本时,该脚本会在成功处理完一个用户后返回一个句点 (.)。如果该脚本未能成功处理用户,则会返回一个感叹号 (!)。

注意:时区提取模式的输出文件不能用作此脚本的输入文件。要创建此脚本的输入文件,可以先将时区提取输出文件的内容粘贴到记事本中,接着将该内容另存为一个新的文档,然后再将该新文档用作输入文件。

在更新模式下日志记录如何工作

Outlook 时区数据更新工具的日志

当运行 Outlook 工具时,它会在临时目录中创建一个日志文件。此文件名为“Outlook Time Zone Update.log”。Msextmz.exe 会提取“Outlook Time Zone Update.log”中的信息,然后在 .ini 文件的 LogDirectory 中指定的目录中创建每个用户的日志文件。

这些文件使用以下格式命名:
MSExTmz-<用户 DN 中的用户 CN>-<随机数>.LOG
例如,Outlook 工具记录以下信息:
MSExTmz-USER3-0x0131273E.LOG
当 Outlook 工具处理具有以下 DN 的用户时便会执行此操作:
/O=FIRST ORGANIZATION/OU=FIRST ADMINISTRATIVE GROUP/CN=RECIPIENTS/CN=USER3

错误文件

如果 Msextmz.exe 无法对任何邮箱运行 Outlook 工具,则会在错误文件中记录该用户的 DN。如果 Outlook 工具成功运行,则 Msextmz.exe 将不会在错误文件中记录任何内容。

日志文件

如果 Msextmz.ini 文件中配置了“日志文件”选项,则还可以从指定的文件中查看 Msextmz.exe 向命令提示符窗口输出的信息。

如何运行 Msextmzcfg.exe

Msextmzcfg.exe 会自动完成以下过程:提取时区、解析每个用户的时区以及生成在更新模式下运行 Msextmzcfg.exe 所需的用户列表和 .ini 文件。我们建议您使用 Msextmzcfg.exe 执行这些步骤,而不是手动执行它们。本部分介绍如何运行 Msextmzcfg.exe。

必需的权限

用于运行 Msextmzcfg.exe 的帐户必须在客户端上拥有下列权限:
  • Exchange 只读管理员
  • 本地管理员

使用 Msextmzcfg.exe 更新 Exchange 服务器的过程示例

  1. 在客户端计算机上,创建一个 Outlook 配置文件,以登录到驻留在要尝试更新的 Exchange 服务器上的邮箱中。确保该配置文件处于联机模式,然后将其配置为默认的配置文件。

    注意:Exchange 服务器必须支持联机模式。
  2. 运行 Msextmzcfg.exe 以启动 Exchange 工具。
  3. 在 Exchange 日历更新工具向导的第一页上,请完成下列过程之一:

    要提取 Exchange 服务器上所有邮箱的时区,请按照下列步骤操作:
    1. 在“服务器名称”框中,键入 Exchange 服务器的友好名称或完全限定的域名 (FQDN)。如果其友好名称包含“.”,请改用 NetBIOS 名称。如果该服务器位于其他 Active Directory 林中,Msextmzcfg.exe 将失败。
    2. 在“提取的输出文件”框中,键入将包含所有邮箱时区信息的文件的名称。
    3. 如果要提取定期会议的时区,请单击以选中“提取定期会议时区”复选框。

      重要说明:如果使用此设置,则执行模式的运行时间将大大延长。默认情况下会清除“提取定期会议时区”复选框。
    4. 单击“Outlook 配置文件名称”列表,然后单击您在步骤 1 中创建的配置文件。
    5. 单击“下一步”。


    要跳过时区提取过程,请按照下列步骤操作:
    1. 单击以选中“跳过时区提取”复选框。默认情况下会清除“跳过时区提取”复选框。
    2. 在“提取的输出文件”框中,键入以前运行时区提取时生成的输出文件的名称。
    3. 在“服务器名称”框中,键入生成步骤 3b 中指定的输出文件时使用的 Exchange 服务器的友好名称或 FQDN。
    4. 单击“下一步”。
  4. 时区提取完成后,Msextmzcfg.exe 会分析输出文件,然后尝试将用户邮箱中的时区映射到实际的操作系统时区。

    如果有任何时区无法匹配,则必须在“映射时区”页上手动映射时区。为此,请在“Windows 时区”列表中单击与用户时区匹配的 Windows 时区,然后单击“下一步”。
  5. 映射过程完成后,Msextmzcfg.exe 会将用户分为以下几组:
    • 仅有一个时区的用户(例如,具有 CDO、Outlook Web Access、Outlook 或定期会议时区的用户)或将多个时区映射到同一操作系统时区的用户
    • 将不同时区映射到不同操作系统时区的用户
    • 不具有任何时区信息的用户
    Msextmzcfg.exe 允许您将“冲突”用户和“不存在”用户的列表保存在单独的文本文件中。为此,请按照下列步骤操作:
    1. 在“时区信息发生冲突的用户”区域中的“输出文件”框中,键入 ConflictUsers.txt
    2. 在“不具有时区信息的用户”区域中的“输出文件”框中,键入 NonExistent.txt
  6. 在“日历更新配置”页上提供必需的信息,以生成更新邮箱时使用的用户列表输入文件、.ini 文件和批处理文件。为此,请按照下列步骤操作:
    1. 在“选择需要更新的时区”列表中,单击以选中要更新的时区的复选框。
    2. 在“批处理文件数目”框中,键入要生成的用户批次。

      如果要缩短更新运行时间,则可以使用此信息。您可以将大型的用户列表分为多个较小的批次,然后在更新模式下运行 Msextmz.exe 的多个实例,从而来实现此目的。此操作应在单独的计算机上执行,并让 Msextmz.exe 的每个实例处理一个单独的用户批次。

      注意:不能在同一台客户端计算机上运行 Msextmz.exe 的多个实例。
    3. 在“Tzmove.exe 路径”框中,键入 Outlook 工具的路径及其参数。如果仅要更新定期会议,请单击以选中“仅定期会议”复选框。
    4. 在“邮箱发送延迟(秒)”框中,键入要在两次邮箱更新之间延迟配置文件创建的秒数。我们建议您使用默认值 0 秒。
    5. 在“每个邮箱的超时(分)”框中,键入 Outlook 工具在超时前要等待的分钟数。我们建议您使用默认值 15 分钟。
  7. 单击“完成”。Msextmzcfg.exe 会在当前执行目录下生成一个子目录。该子目录的名称是 Exchange 服务器的友好名称。该子目录中包含下列文件:
    • MSExTmz_x.ini

      此文件是 Msextmz.exe 在更新模式下运行时使用的 .ini 文件。x 是批号的占位符。
    • Mailboxes_x.txt

      此文件是 Msextmzcfg.exe 在更新模式下运行时使用的用户列表输入文件。x 是批号的占位符。
    • MSExTmz_x.bat

      此文件是在更新模式下对 Mailboxes_x.txt 文件中指定的用户运行 Msextmzcfg.exe 的批处理文件。
    • NonExistent.txt

      此文件包含在邮箱中不具有时区信息的用户的列表。
    • ConflictUsers.txt

      此文件包含时区发生冲突的用户的列表。
  8. 找到以服务器命名的子目录,在记事本中打开 Mailboxes_x.txt 文件,删除所有资源或系统邮箱条目,然后保存 Mailboxes_x.txt 文件。
  9. 请按照下列步骤操作:
    1. 启动 Outlook,然后使用默认的配置文件(而不是提示选择配置文件)来验证 Outlook 是否已正确登录到服务器上。
    2. 验证 Outlook 在启动过程中是否未显示任何提示。如果出现提示,则无法运行 Msextmz.exe。
    3. 验证以下文件是否存在:
      %USERPROFILE%\Local Settings\Application Data\Microsoft\Outlook\Extend.dat
      如果此文件存在,请将其重命名。
    转到以服务器命名的子目录,然后逐个运行批处理文件,从而来更新邮箱。要成功运行批处理文件,所用帐户必须对要更新的邮箱具有完全邮箱访问和代理发送权限。

运行了 Exchange 工具之后的操作事项

安装更新

在更新完环境中的所有 Exchange 服务器后,请在 Exchange 服务器上安装以下更新:
926666 针对 Exchange 2003 Service Pack 2 的 2007 年夏令时更改更新

已知问题

  • Exchange 工具不更新在 Outlook Web Access 中创建的定期会议

    如果您在更新邮箱之前在 Exchange 服务器上安装了知识库文章 926666 中提到的更新,则 Exchange 工具将不更新在 Outlook Web Access 中创建的定期会议。要解决此问题,请先删除更新 926666,接着运行 Exchange 工具,然后再在 Exchange 服务器上重新安装更新 926666。
  • 运行了 Exchange 工具后必须重新启动 Exchange 2007

    运行了 Exchange 工具后,要使 Exchange 2007 Outlook Web Access 正确显示日历项目,必须重新启动 Exchange 服务。
  • 无法安装 Exchange 工具

    如果存在以下两个注册表项当中的任意一个,则无法成功安装 Exchange 工具:
    • HKEY_CLASS_ROOT\Outlook.Application.9
    • HKEY_CLASS_ROOT\Outlook.Application.10
    在此情况下,如果您尝试安装 Exchange 工具,则会收到下面的错误消息:
    Exchange Server Calendar Rebasing Tool cannot be installed with this version of Microsoft Outlook.
    要解决此问题,请删除这些注册表项,并在安装了 Exchange 工具后再还原它们。
  • 某个时区可能不明确

    如果定期日历项目是在 Outlook 2003 或 Outlook 的早期版本中用太平洋 (PST) 时区的 DST 2006 规则创建的,则 Outlook 工具将不会更新它们。由于 Msextmz.exe 运行 Outlook 工具,因此这一问题会影响 Msextmz.exe。

    要解决此问题,请在运行 Msextmz.exe 的计算机上更改注册表,以删除墨西哥时区。接下来,请在更新模式下运行 Msextmzcfg.exe,然后在注册表中还原墨西哥时区。为此,请按照下列步骤操作。

    警告:如果使用注册表编辑器或其他方法错误地修改了注册表,则可能会出现严重问题。这些问题可能需要重新安装操作系统才能解决。Microsoft 不能保证可以解决这些问题。修改注册表需要您自担风险。
    1. 备份注册表。
    2. 依次单击“开始”和“运行”,键入 regedit,然后单击“确定”。
    3. 展开以下子项:
      HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Time Zones
    4. 右键单击“Mexico Standard Time”,然后单击“删除”。
    5. 在“确认项删除”对话框中,单击“是”。
    6. 右键单击“Mexico Standard Time 2”,然后单击“删除”。
    7. 在“确认项删除”对话框中,单击“是”。
    8. 在更新模式下运行 Msextmzcfg.exe。
    9. 通过步骤 1 中创建的备份还原注册表。
    有关如何备份和还原注册表的更多信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
    256986 Microsoft Windows 注册表说明
  • 对每个服务器可以处理的邮箱数存在限制

    在用户列表模式和时区提取模式下,Msextmz.exe 在每个服务器上只能处理 65,535 个邮箱。如果服务器上的邮箱超过 65,535 个,则部分邮箱将无法得到处理。
  • 可能存在会议室分配冲突

    在使用 Outlook 工具时,会议将改为正确的时间。但是,这可能会导致会议室分配冲突。

    如果您运行的是 Exchange Server 2007,我们建议在 Exchange 2007 中将资源预订助理的冲突限制设置为 3。更新了所有邮箱后,这些冲突将自动得到解决。

    如果您使用的是直接预订或自动接受代理,请按照下列步骤更新资源邮箱:

    对于直接预订

    注意:下列步骤要求下载 Microsoft Office Outlook 时区数据更新工具 (Tzmove.exe) 的最新修补程序。
    1. 使用 /FORCEREBASESUPPRESSALLUPDATES 命令行参数对资源邮箱运行 Tzmove.exe(Outlook 工具)。
    2. 在普通模式下对所有其他邮箱运行 Tzmove.exe。
    更新完成后,如果您使用 Outlook 登录到资源邮箱并读取在步骤 2 中发送的更新,则这些会议更新在资源邮箱日历上将显示为“暂定”。如果没有人登录到该资源邮箱,则步骤 1 中更新的原始会议请求在资源邮箱日历上将显示为“已接受”。

    有关 FORCEREBASESUPPRESSALLUPDATES 的更多信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
    933146 Microsoft Office Outlook 时区数据更新工具的修补程序包说明


    对于自动接受代理
    1. 确保自动接受代理正在服务器上运行。
    2. 在客户端计算机上安装该夏令时更新。
    3. 使用 /FORCEREBASESUPPRESSALLUPDATES 命令行参数对启用自动接受代理的资源邮箱运行 Tzmove.exe(Outlook 工具)。
    4. 再次验证自动接受代理是否正在运行。这一点十分重要,因为它可以确保用户能够收到接受他们组织的已更新会议的邮件。
    5. 在普通模式下对所有其他邮箱运行 Tzmove.exe。
  • 公共文件夹日历

    Exchange 工具不更新公共文件夹日历。有关如何更新公共文件夹日历的信息,请参见 Outlook 工具文档。
  • 必须使用命令行中的“运行身份”

    如果要使用命令行中的“运行身份”运行 Msextmz.exe,请确保也使用“运行身份”配置注册表编辑器,以设置注册表中的 PickLogonProfile 值。
  • Msextmz.exe 可能停止响应

    全局编录服务器的问题可能导致 Msextmz.exe 停止响应。如果出现此情况,请按照下列步骤操作:
    1. 停止 Msextmz.exe。
    2. 如果 Msextmz.ini 中设置了 Logfile 参数,请找出刚才正在处理的邮箱。日志文件中的“正在处理邮箱”条目将提供 Msextmz.exe 停止响应时处理的邮箱的用户 DN。

      如果 Msextmz.ini 中未设置 Logfile 参数,则可以在命令提示符窗口中找到“正在处理邮箱”信息。

      只要用户邮箱位于 Msextmz.exe 停止响应时正在处理的邮箱之后,便不会得到处理。这适用于 MSEXTMZ.exe 运行时用作输入文件的 ServerName_TimeZone_Input_File.txt 中的邮箱。
    3. 创建一个新的输入文件并令其包含未处理邮箱的用户 DN。
    4. 在使用这个新输入文件再次运行 Msextmz.exe 之前,请确保处理上次运行时生成的错误文件中的用户。
  • 可以在同一环境中运行 Outlook 工具和 Exchange 工具

    您可以在同一环境中运行 Outlook 工具和 Exchange 工具。如果您对已用 Outlook 工具更新的邮箱运行 Exchange 工具(或相反),将不会产生任何副作用。但是,如果管理员运行 Exchange 工具,用户将不再需要单独运行 Outlook 工具。
  • 提醒的显示时间晚于预期

    对于使用 Exchange 工具更新的邮箱,如果 Outlook 从未在联机模式下连接到该邮箱,将不会更新该邮箱的非会议提醒。在此情况下,这些提醒的显示时间将比预期晚一个小时。

    如果 Outlook 从未在联机模式下实现连接,则必须调整 Outlook 时区更新工具发现的错误的日历约会提醒,另外,邮箱中将不存在提醒搜索文件夹。因此,该工具将不会更新电子邮件项目、联系人或其他提醒。例如,该工具将不会更新需要在以后某个时间跟进的电子邮件项目上的提醒,也不会更新设置了提醒的任务项目上的提醒。
  • 运行时间可能较长

    Msextmz.exe 以单线程模式运行。因此,在对多个邮箱运行该工具时,它可能需要数个小时。

    现提供以下数字供您参考:如果使用 9 个客户端,Microsoft IT 能够在 16 个小时内更新约 53,000 个邮箱。其更新速度相当于每个客户端每分钟更新 6.13 个邮箱。 会议请求中的与会者数应不影响更新模式的运行时间。这是因为,从客户端的角度来讲,向一个收件人发送会议更新与向 100 个收件人发送会议更新所需的时间相同。 与会者的数目会影响会议更新的副本数。但这属于邮件流问题,与运行时间无关。

    会议请求中的与会者数应不影响更新模式的运行时间。这是因为,从客户端的角度来讲,向一个收件人发送会议更新与向一百个收件人发送会议更新所需的时间相同。

    与会者的数目会影响会议更新的副本数。但这属于邮件流问题,与运行时间无关。
  • 在更新大量邮箱后,事件日志可能会出现空间不足的问题

    对于每个成功的更新,Tzmove.exe 都会生成一个来源为 TZMOVE、事件 ID 为 32 的信息事件。如果事件太多,则会导致应用程序日志超出磁盘上分配的空间。在更新模式下,Msextmz.exe 依靠这些事件来确定 Tzmove.exe 的执行是否成功。对于 Msextmz.exe 要尝试更新的邮箱,如果 Msextmz.exe 无法找到与其关联的相应 Tzmove.exe 事件,Msextmz.exe 将假定更新失败。这样,Msextmz.exe 将在 error.txt 文件中记录该邮箱的 DN。要避免此问题,我们建议将事件日志设置为最大并允许将其覆盖。
  • 因检测到以前版本的“Microsoft Exchange 日历更新工具”而无法安装。请先卸载它们,然后再次运行此安装程序。

    如果您以前安装了 Exchange 日历更新工具 1.0 版,则在安装 2.0 版之前必须先卸载 1.0 版。1.0 版以自解压缩的可执行程序的形式分发,它包含两个 MSI 程序包:Msextmz.msi 和 Msextmzcfg.msi。在安装 2.0 版之前,您必须先卸载这两个程序包。如果您在安装 2.0 版时仍遇到问题,请尝试使用 *.msi 程序包而不是“添加或删除程序”工具重新安装并卸载 1.0 版。接下来,请重新启动计算机,然后安装 2.0 版。如果这一切全部失败,请直接提取 *.msi 程序包中的二进制文件。

错误消息和解决方案

  • Unable find mailbox timezone:Error 0x80004005
    此错误消息可能是由以下任一问题导致的:
    • 该工具在特定用户的邮箱中无法找到任何时区值。要解决此问题,请尝试向 Msextmz.ini 文件中添加“ReadCalendarTimeZones=1”(不包含引号),以强制该工具在定期日历项目中检查时区信息。您可以使用上次运行时收到的错误日志中的 DN 创建一个新的输入文件。
    • 您在从错误的目录中引用 Tzmove.exe。要解决此问题,请将下载的安装文件解压缩到 Msextmz 所在的文件夹,或者更新 Msextmz.ini 以使其包含 Tzmove.exe 在您所用工作站上的完整安装路径。

      注意:在下载 Microsoft Office Outlook 时区数据更新工具时,Tzmove.exe 文件是该实际工具的安装程序。如果引用了该安装程序,将导致在运行 Msextmz 时出现错误。
    • 您用于运行 Msextmz 的帐户不具有完全邮箱权限,并且未被授予正确的 Exchange 权限。要解决此问题,请从 Exchange Server 计算机上运行“授予邮箱权限”脚本。
  • Unable to process mailbox /O=CONTOSO/OU=<第一个管理组>/CN=RECIPIENTS/CN=TESTMB01 - 0x80004005
    请仔细检查 legacyExchangeDN 并进行任何必要的更正。要确保该值准确无误,请使用 ADSIEdit 复制并粘贴该值。
  • Unable open mailbox table for server /O=CompanyRoot/ OU=IT/cn=Configuration/cn=Servers/cn=EXCH01. Error 80040115
    此错误属于 RPC 错误。请仔细检查 legacyExchangeDN 并进行任何必要的更正。
    Please Select the Valid Server
    您需要服务器的可分辨名称 (DN)。该 DN 应与下面列出的 DN 类似:
    ServerDN:/O=CompanyRoot/OU=IT/cn=Configuration/cn=Servers/cn=EXCH01
  • 应用程序正常初始化(0xc0000135)失败。请单击“确定”,终止应用程序
    出现此错误消息是因为未安装 .NET Framework 2.0。
  • HrTestMailboxAccess:Unable Open mailbox - 0x8004011D.
    如果您在更新操作期间收到此错误消息,那么您所使用的帐户没有针对邮箱的完全访问权限。帐户必须具有针对所有邮箱的完全邮箱访问权限,这样工具才能更新邮箱。

    验证已使用“配置 Msextmz.exe 的权限”部分中描述的方法授予了正确的权限。

参考

“授予邮箱权限”脚本

Option Explicit
' For FileSystemObject
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
Const TristateTrue = -1
Const TristateUseDefault = -2
Const TristateFalse = 0

'Permission Type: Allow or Deny
Const ADS_ACETYPE_ACCESS_ALLOWED = &H0
Const ADS_ACETYPE_ACCESS_DENIED = &H1
Const ADS_ACETYPE_ACCESS_ALLOWED_OBJECT = &H5
Const ADS_ACETYPE_ACCESS_DENIED_OBJECT = &H6

Const ADS_ACEFLAG_INHERIT_ACE = &H2
Const ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE = &H4
Const ADS_ACEFLAG_INHERIT_ONLY_ACE = &H8
Const ADS_ACEFLAG_INHERITED_ACE = &H10
Const ADS_ACEFLAG_VALID_INHERIT_FLAGS = &H1f
Const ADS_ACEFLAG_SUCCESSFUL_ACCESS = &H40
Const ADS_ACEFLAG_FAILED_ACCESS = &H80

'Declare ADSI constants
Const ADS_SCOPE_SUBTREE = 2
Const ADS_OPTION_SECURITY_MASK = 3
Const ADS_OPTION_REFERRALS	= 1
Const ADS_SECURITY_INFO_DACL = 4
Const ADS_CHASE_REFERRALS_NEVER = &h00 
Const ADS_CHASE_REFERRALS_SUBORDINATE = &h20 
Const ADS_CHASE_REFERRALS_EXTERNAL = &h40

'Microsoft Exchange 
Const EX_MB_SEND_AS_ACCESSMASK  = &H00100
Const EX_FULLMAILBOX_ACCESSMASK = 1
Const EX_MB_SEND_AS_GUID = "{AB721A54-1E2F-11D0-9819-00AA0040529B}"

'Application Parameter Index
Const ARG_INDEX_MODE = 0
Const ARG_INDEX_USERNAME = 1
Const ARG_INDEX_FILENAME = 2
Const MIN_ARG = 1

Const MODE_INVALID = -1 
Const MODE_ADD = 0
Const MODE_REMOVE = 1

Const ADD = "-ADD"
Const REMOVE = "-REMOVE"

'Application Const String
Const EMPTYSTRING = ""
Const ERROR_FILENAME = "GrantMailboxPermission.err"
Const OUTPUT_FILENAME = "GrantMailboxPermission.log"
Dim OUTPUT_DELIMITER
OUTPUT_DELIMITER = vbTab

'Logging file
Dim objFSO
Dim objfileError
Dim objfileOutput
Dim objfileImport
Dim objconn
Dim objCommand
Dim rootDSE
Dim sDomainContainer
Dim sUserLDAPPath
Dim objUser
Dim objSDNTsecurity
Dim objDACLNT
Dim objDACLEX
Dim objSDMailbox
Dim fFMA
Dim fSendAs
Dim AccessTypeForFMA
Dim AccessTypeForSendAS
Dim fAddedFMA
Dim fAddedSendAs
Dim fRemovedFMA
Dim fRemovedSendAs
Dim sArraySplit
Dim sOneRow
Dim sGrantedUser
Dim dArgCount
Dim cScriptMode
Dim dArgExpected
Dim fOneError

On Error Resume Next
'Parameter Checking
dArgCount = Wscript.Arguments.Count
If (dArgCount < MIN_ARG) Then
	DisplaySyntax
End If

cScriptMode = MODE_INVALID
Select Case UCase(WScript.Arguments(ARG_INDEX_MODE))
	Case ADD
		cScriptMode = MODE_ADD
		dArgExpected = ARG_INDEX_FILENAME + 1
	Case REMOVE
		cScriptMode = MODE_REMOVE
		dArgExpected = ARG_INDEX_MODE + 1
	Case Else
		cScriptMode = MODE_INVALID
End Select

If (cScriptMode = MODE_INVALID Or dArgCount <> dArgExpected) Then
	DisplaySyntax
End If

If (cScriptMode = MODE_ADD) Then
	sGrantedUser = WScript.Arguments(ARG_INDEX_USERNAME)
	If (IsValidUserName(sGrantedUser) = False) Then
		DisplaySyntax
	End If
End If

CreateImportExportFiles

If (cScriptMode = MODE_ADD) Then
	err.Clear
	
	'Prepare LDAP connection
	Set objconn = CreateObject("ADODB.Connection")
	Set objCommand = CreateObject("ADODB.Command")
	objconn.Provider = "ADSDSOObject"
	objconn.Open "ADs Provider"
	If (err.number <> 0) Then
		WScript.StdOut.WriteLine("Failed to bind to Active Directory server, error:" & err.Description)
		objfileError.WriteLine("Failed to bind to Active Directory server, error:" & err.Description)
		WScript.Quit
	End If
		
	Set rootDSE = GetObject("LDAP://rootDSE")
	sDomainContainer = rootDSE.Get("defaultNamingContext")
	If (err.number <> 0) Then
		WScript.StdOut.WriteLine("Failed to find a Domain Container:" & err.Description)
		objfileError.WriteLine("Failed to find a Domain Container:" & err.Description)
		WScript.Quit
	End If
		
	Set objCommand.ActiveConnection = objconn

	Do While objfileImport.AtEndOfStream <> True
		fOneError = False
		sUserLDAPPath = EMPTYSTRING
		err.Clear

		sOneRow = Trim(objfileImport.ReadLine)
		If sOneRow <> EMPTYSTRING Then
		
		    sUserLDAPPath = GetLDAPPathFromLegacyDN(sOneRow)
		    If (err.number <> 0) Then
			    objfileError.WriteLine("Failed to get user's LDAP path from " & sOneRow)
			    fOneError = True
			    err.Clear
		    End If

		    If (fOneError = False) Then
			    Set objUser = GetObject(sUserLDAPPath)
			    If (err.number <> 0) Then
				    objfileError.WriteLine("Failed to get user object from " & sUserLDAPPath)
				    objfileError.WriteLine("Error: " & err.Description)
				    fOneError = True
				    err.Clear
			    End If
		    End If
    	
		    If (fOneError = False) Then
			    Set objSDMailBox = objUser.MailboxRights
			    Set objDACLEX = objSDMailbox.DiscretionaryAcl
			    Set objSDNTsecurity = objUser.ntSecurityDescriptor
			    Set objDACLNT = objSDNTsecurity.DiscretionaryAcl
			    If (err.number <> 0) Then
				    objfileError.WriteLine("Failed to get DACL of " & sUserLDAPPath)
				    objfileError.WriteLine("Error: " & err.Description)
				    fOneError = True
				    err.Clear
			    End If
		    End If

		    ' Check Full Mailbox Access and Send As permission
		    fFMA = False
		    fSendAs = False
		    AccessTypeForFMA = ADS_ACETYPE_ACCESS_ALLOWED
		    AccessTypeForSendAS = ADS_ACETYPE_ACCESS_ALLOWED

		    If (fOneError = False) Then
			    CheckFullMailboxAccess objDACLEX, sGrantedUser, fFMA, AccessTypeForFMA
			    CheckSendAs objDACLNT, sGrantedUser, fSendAs, AccessTypeForSendAS
			    If (err.number <> 0) Then
				    objfileError.WriteLine("Failed to Check permission of " & sUserLDAPPath)
				    objfileError.WriteLine("Error: " & err.Description)
				    fOneError = True
				    err.Clear
			    End If
		    End If

		    'If we don't have either SendAS or FMA, we're going to add these permission
		    If ( (AccessTypeForFMA = ADS_ACETYPE_ACCESS_DENIED) Or (AccessTypeForSendAs = ADS_ACETYPE_ACCESS_DENIED_OBJECT) ) Then
			    'Deny access already granted, won't add permission to this user
			    objfileError.WriteLine("Deny permission already added: " & sUserLDAPPath)
			    fOneError = True
		    End If
    		
		    If ( fOneError = False And ((fFMA = False) Or (fSendAs = False)) ) Then
			    fAddedFMA = False
			    fAddedSendAs = False
    			
			    If (fFMA = False) Then
				    'Add FMA permission
				    err.Clear
				    AddAce objDACLEX, sGrantedUser, EX_FULLMAILBOX_ACCESSMASK, ADS_ACETYPE_ACCESS_ALLOWED, ADS_ACEFLAG_INHERIT_ACE, 0,0,0
				    objSDMailbox.DiscretionaryAcl = objDACLEX
				    objUser.MailboxRights = Array(objSDMailbox)
				    If ( err.number <> 0 ) Then
					    objfileError.WriteLine("Failed to add FullMailbox Access: " & sUserLDAPPath)
					    objfileError.WriteLine("Error: " & err.Description)
					    fOneError = True
					    fAddedFMA = False
					    err.Clear
				    Else
					    fAddedFMA = True
				    End If
			    End If
    			
			    If (fSendAs = False) Then
				    'Add SendAs permission
				    err.Clear
				    AddAce objDACLNT, sGrantedUser, EX_MB_SEND_AS_ACCESSMASK, ADS_ACETYPE_ACCESS_ALLOWED_OBJECT, 0,1, EX_MB_SEND_AS_GUID, 0
				    objSDNTsecurity.DiscretionaryAcl = objDACLNT
				    objUser.Put "ntSecurityDescriptor", Array( objSDNTsecurity )
				    objUser.SetOption ADS_OPTION_SECURITY_MASK, ADS_SECURITY_INFO_DACL
				    If ( err.number <> 0 ) Then
					    objfileError.WriteLine("Failed to add SendAs permission: " & sUserLDAPPath)
					    objfileError.WriteLine("Error: " & err.Description)
					    fOneError = True
					    fAddedSendAs = False
					    err.Clear
				    Else
					    fAddedSendAs = True
				    End If
			    End If

			    If (fOneError = False ) Then 
				    objUser.SetInfo
				    If (err.number <> 0) Then
					    objfileError.WriteLine("Failed to update user: " & sUserLDAPPath)
					    objfileError.WriteLine("Error: " & err.Description)
					    fOneError = True
					    err.Clear		
				    Else
					    'Update Logging
					    objfileOutput.WriteLine(sUserLDAPPath & OUTPUT_DELIMITER & fAddedFMA & OUTPUT_DELIMITER & fAddedSendAs)		
				    End If
			    End If
		    End If

		    Set objUser = Nothing
		    Set objSDNTsecurity = Nothing
		    Set objDACLNT = Nothing
		    Set objDACLEX = Nothing
		    Set objSDMailBox = Nothing

		    If (fOneError = True) Then
			    WScript.StdOut.Write("!")
		    Else
			    WScript.StdOut.Write(".")
		    End If
End If
	Loop

Set rootDSE = Nothing
Set objCommand = Nothing
Set objconn = Nothing

End If

If (cScriptMode = MODE_REMOVE) Then
	'Retreive the granted user from the first line of import file
	sGrantedUser = objfileImport.ReadLine
	If (IsValidUserName(sGrantedUser) = False) Then
		WScript.StdOut.WriteLine("Invalid User in import file. please check import file..")
		objfileError.WriteLine("Invalid User in import file. please check import file..")
		WScript.Quit
	End If
	
	Do While objfileImport.AtEndOfStream <> True
		fOneError = False
		sUserLDAPPath = EMPTYSTRING
		fAddedFMA = False
		fAddedSendAs = False
		fRemovedFMA = False
		fRemovedSendAs = False
		err.Clear

		sOneRow = objfileImport.ReadLine
		sArraySplit = Split(sOneRow, OUTPUT_DELIMITER)

		'First column is Ldap path
		sUserLDAPPath = sArraySplit(0)
		'Second column is FullMailbox Permission
		fAddedFMA = sArraySplit(1)
		'Third column is SendAs
		fAddedSendAs = sArraySplit(2)

		Set objUser = GetObject(sUserLDAPPath)
		If (err.number <> 0) Then
			objfileError.WriteLine("Failed to get user object from " & sUserLDAPPath)
			objfileError.WriteLine("Error: " & err.Description)
			fOneError = True
			err.Clear
		End If
		
		If ((fOneError = False) And (fAddedFMA = "True")) Then		
			Set objSDMailBox = objUser.MailboxRights
			Set objDACLEX = objSDMailbox.DiscretionaryAcl
			fRemovedFMA = RemoveFullMailboxAccess(objDACLEX, sGrantedUser)
			If (err.number <> 0) Then
				objfileError.WriteLine("Failed to Remove Full MailboxAccess from " & sUserLDAPPath)
				objfileError.WriteLine("Error: " & err.Description)
				fOneError = True
				err.Clear
			End If
			
			If (fRemovedFMA = False) Then
				objfileError.WriteLine("Couldn't find Full mailbox access permission on " & sUserLDAPPath)
			End If
			
			If ((fOneError = False) And (fRemovedFMA = True)) Then
				objSDMailbox.DiscretionaryAcl = objDACLEX
				objUser.MailboxRights = Array(objSDMailbox)
			End If
		End If

		If ((fOneError = False) And (fAddedSendAs = "True")) Then		
			Set objSDNTsecurity = objUser.ntSecurityDescriptor
			Set objDACLNT = objSDNTsecurity.DiscretionaryAcl

			fRemovedSendAs = RemoveSendAs(objDACLNT, sGrantedUser)
			If (err.number <> 0) Then
				objfileError.WriteLine("Failed to Remove SendAs from " & sUserLDAPPath)
				objfileError.WriteLine("Error: " & err.Description)
				fOneError = True
				err.Clear
			End If

			If (fRemovedSendAs = False) Then
				objfileError.WriteLine("Couldn't find SendAs permission on " & sUserLDAPPath)
			End If
			
			If ((fOneError = False) And (fRemovedSendAs = True)) Then
				objSDNTsecurity.DiscretionaryAcl = objDACLNT
				objUser.Put "ntSecurityDescriptor", Array( objSDNTsecurity )
				objUser.SetOption ADS_OPTION_SECURITY_MASK, ADS_SECURITY_INFO_DACL
			End If
		End If

		If ((fOneError = False) And (fRemovedFMA Or fRemovedSendAs)) Then
			objUser.SetInfo
			If (err.number <> 0) Then
				objfileError.WriteLine("Failed to update ADSI for user: " & sUserLDAPPath)
				objfileError.WriteLine("Error: " & err.Description)
				fOneError = True
				err.Clear		
			Else 
				If ( fRemovedFMA Or fRemovedSendAs ) Then
					'Update Logging
					objfileError.WriteLine("Removed Permission from " & sUserLDAPPath & OUTPUT_DELIMITER & fRemovedFMA & OUTPUT_DELIMITER & fRemovedSendAs)
				End If
			End If
		End If

		If (fOneError = True) Then
			WScript.StdOut.Write("!")
		Else
			WScript.StdOut.Write(".")
		End If
	Loop
End If

CloseImportexportFiles

Function IsValidUserName (sUserName)
	Dim dPosition
	dPosition = InStr(1, sUserName, "\")
	If (dPosition = 0 ) Then
		IsValidUserName = False
		objfileError.WriteLine("Invalid User:" & sUserName)
	Else
		IsValidUserName = True
	End If
End Function

Function CheckSendAs (objNTSD, sUser, fSendAs, AccessType)
	Dim intACECount
	Dim objACE
	
	err.Clear
	fSendAs = False
	AccessType = ADS_ACETYPE_ACCESS_ALLOWED
	intACECount = objNTSD.AceCount

	If intACECount Then
		For Each objACE In objNTSD
			err.Clear
			If ( (UCase(objACE.Trustee) = UCase(sUser)) And (objACE.ObjectType = EX_MB_SEND_AS_GUID) ) Then
				fSendAs = True
				AccessType = objACE.AceType
			End If
		Next
	End If	

	If (err.number <> 0) Then
		objfileError.WriteLine("Check SendAs permissions Failed: " & sUser)
		objfileError.WriteLine("Error: " & err.Description)
		err.Clear
		fOneError = True
	End If
	Set objACE = Nothing
End Function

Function CheckFullMailboxAccess (objACL, sUser, fFoundFMA, AccessType)
	Dim intACECount
	Dim objACE

	err.Clear
	fFoundFMA = False
	AccessType = ADS_ACETYPE_ACCESS_ALLOWED
	intACECount = objACL.AceCount
	If intACECount Then
		For Each objACE In objACL
			If ( (UCase(objACE.Trustee) = UCase(sUser)) And ((objACE.AccessMask And EX_FULLMAILBOX_ACCESSMASK) <> 0)) Then
				fFoundFMA = True
				AccessType = objACE.AceType
			End If
		Next
	End If

	If (err.number <> 0) Then
		objfileError.WriteLine("Check FullMailbox permissions Failed: " & sUser)
		objfileError.WriteLine("Error: " & err.Description)
		err.Clear
		fOneError = True
	End If
	Set ObjACE = Nothing
End Function

Function RemoveSendAs (objNTSD, sUser)
	Dim intACECount
	Dim objACE
	Dim fFound
	
	fFound = False
	intACECount = objNTSD.AceCount
	
	If intACECount Then
		For Each objACE In objNTSD
			If ((UCase(objACE.Trustee) = UCase(sUser)) And (objACE.ObjectType = EX_MB_SEND_AS_GUID) ) Then
				objNTSD.RemoveAce objACE
				fFound = True
			End If
		Next
	End If

	RemoveSendAs = fFound		
End Function

Function RemoveFullMailboxAccess (objACL, sUser)
	Dim intACECount
	Dim objACE
	Dim fFound
	
	fFound = False
	intACECount = objACL.AceCount
	
	If intACECount Then
		For Each objACE In objACL
			If((0 <> Instr(UCase(objACE.Trustee), UCase(sUser))) And (objACE.AccessMask And EX_FULLMAILBOX_ACCESSMASK) <> 0) Then
				objACE.AccessMask = (objACE.AccessMask Xor EX_FULLMAILBOX_ACCESSMASK)
				fFound = True
			End If
		Next
	End If

	RemoveFullMailboxAccess = fFound		
End Function

Function GetLDAPPathFromLegacyDN (sLegacyDN)
	Dim rsUsers
	Dim sLdapPath
	
	objCommand.CommandText = "<GC://" & sDomainContainer & ">;(&(&(& (mailnickname=*) (| (&(objectCategory=person)(objectClass=user)(legacyExchangeDN=" & sLegacyDN & ")) ))));adspath;subtree"
	objCommand.Properties("searchscope") = ADS_SCOPE_SUBTREE
	objCommand.Properties("Page Size") = 10
	objCommand.Properties("Timeout") = 30 
	objCommand.Properties("Chase referrals") = (ADS_CHASE_REFERRALS_SUBORDINATE Or ADS_CHASE_REFERRALS_EXTERNAL)

	err.Clear	
	Set rsUsers = objCommand.Execute
	If (err.number <> 0) Then
		objfileError.WriteLine("Search for mailbox owners failed, error:" & err.Description)
		fOneError = True
	End If
	
	If (rsUsers.RecordCount = 0) Then
		objfileError.WriteLine("No mailbox owner user accounts found for " & sLegacyDN & " in " & sDomainContainer & ".")
		fOneError = True		
	End If

	If (rsUsers.RecordCount > 1) Then
		objfileError.WriteLine("Multiple mailboxs owner user accounts found for " & sLegacyDN & " in " & sDomainContainer & ".")
		fOneError = True		
	End If

	sLdapPath = Replace(rsUsers.Fields(0).Value, "GC://", "LDAP://")	
	GetLDAPPathFromLegacyDN = sLdapPath
	Set rsUsers = Nothing
End Function

Function CloseImportexportFiles

	objfileError.WriteLine("*******************************************************")
	objfileError.WriteLine("End at " & Date & " " & Time)
	objfileError.WriteLine("*******************************************************")

	objFSO.Close
	objfileError.Close
	objfileOutput.Close
	objfileImport.Close
	
	Set objFSO = Nothing
	Set objfileError = Nothing
	Set objfileOutput = Nothing
	Set objfileImport = Nothing
End Function

Function CreateImportExportFiles
	Dim sErrorsFileName
	Dim sImportFileName
	Dim sOutputFileName

	err.Clear
	Set objFSO = CreateObject("Scripting.FileSystemObject")
	sErrorsFileName = ERROR_FILENAME
	sImportFileName = EMPTYSTRING
	sOutputFileName = EMPTYSTRING

	Select Case cScriptMode
		Case MODE_ADD
			sImportFileName = WScript.Arguments(ARG_INDEX_FILENAME)
			sOutputFileName = OUTPUT_FILENAME
		Case MODE_REMOVE
			sImportFileName = OUTPUT_FILENAME 'Use output file name as import file
			sOutputFileName = EMPTYSTRING	
		Case Else
			DisplaySyntax
	End Select

	Set objfileError = objFSO.OpenTextFile(sErrorsFileName, ForAppending, True, TristateTrue)
	objfileError.WriteLine("*******************************************************")
	objfileError.WriteLine("Start at " & Date & " " & Time)
	objfileError.WriteLine("*******************************************************")

	If (cScriptMode = MODE_REMOVE) Then
		Set objfileImport = objFSO.OpenTextFile(sImportFileName, ForReading, False, TristateTrue)
	Else
		Set objfileImport = objFSO.OpenTextFile(sImportFileName, ForReading, False, TristateFalse)
	End If

	If (sOutputFileName <> EMPTYSTRING) Then
		'Check if output file already exists.
		If (objFSO.FileExists(sOutputFileName)) Then
			Set objfileOutput = objFSO.OpenTextFile(sOutputFileName, ForReading, False, TristateTrue)
			sOneRow = objfileOutput.ReadLine
			'If user name in the file is different from parameter, we can't proceed.
			If ( sOneRow <> sGrantedUser ) Then
				WScript.StdOut.WriteLine("The Domain\User must be the same as " & sOneRow )
				WScript.Quit
			End If
			Set objfileOutput = objFSO.OpenTextFile(sOutputFileName, ForAppending, True, TristateTrue)
		Else
			Set objfileOutput = objFSO.OpenTextFile(sOutputFileName, ForWriting, True, TristateTrue)
			'The first line of Log file is the user who is going to be granted the permissions
			objfileOutput.WriteLine(sGrantedUser)
		End If
	End If
	
	If (err.number <> 0) Then
		WScript.StdOut.WriteLine("Failed to open Log file, error:" & err.Description)
		WScript.Quit
	End If
End Function

Function AddAce(dacl, TrusteeName, gAccessMask, gAceType, gAceFlags, gFlags, gObjectType, gInheritedObjectType)
	Dim Ace1
	
	Set Ace1 = CreateObject("AccessControlEntry")
	Ace1.AccessMask = gAccessMask
	Ace1.AceType = gAceType
	Ace1.AceFlags = gAceFlags
	Ace1.Flags = gFlags
	Ace1.Trustee = TrusteeName
	'Determine whether ObjectType has to be set
	If CStr(gObjectType) <> "0" Then
		Ace1.ObjectType = gObjectType
	End If

	'Determine whether InheritedObjectType has to be set.
	If CStr(gInheritedObjectType) <> "0" Then
		Ace1.InheritedObjectType = gInheritedObjectType
	End If
	dacl.AddAce Ace1

Set Ace1 = Nothing
End Function

Function DisplaySyntax
	WScript.StdOut.WriteLine("Syntax:")
	WScript.StdOut.WriteLine()
	WScript.StdOut.WriteLine("Grant Full mailbox access and SendAs permission to USER based on IMPORT_FILE:")
	WScript.StdOut.WriteLine("    CSCRIPT " & WScript.ScriptName & " -Add DOMAIN\USER IMPORT_FILE")
	WScript.StdOut.WriteLine("    NOTE: """ & OUTPUT_FILENAME & """ will be created for -Remove option ")
	WScript.StdOut.WriteLine()
	WScript.StdOut.WriteLine("Remove Full mailbox access and SendAs permission based on " & OUTPUT_FILENAME & ":")
	WScript.StdOut.WriteLine("    CSCRIPT """ & WScript.ScriptName & """ -Remove ")
	WScript.StdOut.WriteLine()
	WScript.StdOut.WriteLine("For all modes, errors are saved to " & ERROR_FILENAME )

	WScript.Quit	
End Function

修订

收起该表格展开该表格
版本日期更改
1.02007 年 1 月 11 日原始版本
2.02007 年 1 月 12 日编辑性更改
3.02007 年 2 月 7 日重写整篇文章
3.12007 年 2 月 8 日更新了下载中心 URL
3.22007 年 2 月 8 日编辑性更改
4.02007 年 2 月 9 日添加了有关会议室冲突的新信息
4.12007 年 2 月 12 日在“适用于”部分中添加了 Exchange 2003 Enterprise Edition
4.22007 年 2 月 12 日更正了录入错误
4.32007 年 2 月 12 日更正了注意事项中的步骤编号
5.02007 年 2 月 13 日在“如何安装 Exchange 工具”部分中添加了虚拟机信息
6.02007 年 2 月 15 日重写了“提醒的显示时间晚于预期”部分
7.02007 年 2 月 15 日添加了 Microsoft Exchange 日历更新工具包的虚拟机下载信息
8.02007 年 2 月 16 日在“运行 Exchange 工具之前的操作事项”部分中添加了有关 Exchange 系统管理工具的信息
8.12007 年 2 月 19 日更正了“如何运行 Msextmzcfg.exe”部分中的文件名
8.22007 年 2 月 20 日在“授予邮箱权限”脚本部分中的 User_Name 和 File_Name 之间添加了空格
9.02007 年 2 月 20 日重写文章
10.02007 年 2 月 20 日内部元数据更新
10.12007 年 2 月 20 日更正了录入错误
10.22007 年 2 月 20 日更正了录入错误
10.32007 年 2 月 20 日更正了录入错误
10.42007 年 2 月 21 日更正了录入错误
11.02007 年 2 月 22 日添加了有关第 2 版 Exchange 工具的信息
11.12007 年 2 月 22 日更正了录入错误
11.22007 年 2 月 23 日添加了指示文章修订的表格
12.02007 年 2 月 26 日添加了有关事件日志空间的信息以及有关错误消息及其解决方案的信息
13.02007 年 2 月 27 日删除了虚拟机信息的下载 URL 并添加了指向 933185 的交叉引用
14.02007 年 2 月 28 日在“已知问题”部分中将第一个项目符号内的文本更改为包含 KB926666
15.02007 年 2 月 27 日添加了虚拟机信息
16.02007 年 2 月 28 日在“对于直接预订”部分中添加了有关 Microsoft Office Outlook 时区数据更新工具 (Tzmove.exe) 最新修补程序的信息。添加了指向 933146 的交叉引用
16.12007 年 2 月 28 日更正了表格标签
17.02007 年 3 月 1 日删除了 Exchange Server 5.5 信息
收起该表格展开该表格
18.02007 年 3 月 8 日添加了关于“HRTestMailboxAccess”的错误消息

属性

文章编号: 930879 - 最后修改: 2007年11月26日 - 修订: 19.2
这篇文章中的信息适用于:
  • Microsoft Exchange Server 2007 Enterprise Edition
  • Microsoft Exchange Server 2007 Standard Edition
  • Microsoft Exchange Server 2003 Enterprise Edition
  • Microsoft Exchange Server 2003 Standard Edition
  • Microsoft Exchange 2000 Enterprise Server
  • Microsoft Exchange 2000 Server 标准版
关键字:?
kbhowto kbinfo kbexpertiseinter KB930879
Microsoft和/或其各供应商对于为任何目的而在本服务器上发布的文件及有关图形所含信息的适用性,不作任何声明。 所有该等文件及有关图形均"依样"提供,而不带任何性质的保证。Microsoft和/或其各供应商特此声明,对所有与该等信息有关的保证和条件不负任何责任,该等保证和条件包括关于适销性、符合特定用途、所有权和非侵权的所有默示保证和条件。在任何情况下,在由于使用或运行本服务器上的信息所引起的或与该等使用或运行有关的诉讼中,Microsoft和/或其各供应商就因丧失使用、数据或利润所导致的任何特别的、间接的、衍生性的损害或任何因使用而丧失所导致的之损害、数据或利润不负任何责任。

提供反馈

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com