【问题标题】:Win32: Suggestions for manifested app's testing vs deploymentWin32:清单应用程序测试与部署的建议
【发布时间】:2010-12-15 03:16:05
【问题描述】:

从 Windows Vista 开始,Microsoft 添加了一类兼容性填充程序,允许应用程序假设它具有管理 文件注册表 访问权限继续发挥作用。

换句话说:在 Windows XP 上失败的应用程序将在 Windows Vista 上运行。

这些操作系统提供的错误修复可以通过在应用程序清单中添加一个部分来禁用,声明应用程序应该运行asInvoker

<!-- Disable Windows Vista standard user compatability heuristics -->
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
   <security>
      <requestedPrivileges>
         <requestedExecutionLevel level="asInvoker"/>
      </requestedPrivileges>
   </security>
</trustInfo>

理想情况下,开发人员会测试他们的应用程序以确保它不(不必要地)需要管理权限。为了让我对此进行测试,我需要将其显示为 asInvoker

但归根结底,我不会将应用程序发布给客户以asInvoker如果我确实错过了什么,我不希望用户受到影响。我想要微软的操作系统来修正我的错误。此解决方案的问题是:

  • 我必须在发布前修改 manfiest
  • 我永远不会知道我错过了什么,因为它们在 Windows Vista 上正常工作

Windows 7's supportedOS manifiest entires 也出现了类似的难题。您可以向应用程序添加一个清单,指明您设计和测试的 Windows 版本:

<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> 
   <application> 
      <!--The ID below indicates application support for Windows Vista -->
      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> 
      <!--The ID below indicates application support for Windows 7 -->
      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
   </application> 
</compatibility>

对于 supportedOS 项,操作系统预先知道您是为哪个操作系统设计的。如果您不说您支持 Windows 7,这会将您的应用程序置于 Windows Vista 的上下文中:


(来源:msdn.com

此操作类似于在某些兼容模式下运行应用程序,例如:

  • Windows Server 2008(Service Pack 1)
  • Windows Vista(Service Pack 2)
  • Windows Vista(Service Pack 1)
  • Windows Vista
  • Windows Server 2003(Service Pack 1)
  • Windows XP(Service Pack 2)
  • Windows 2000
  • Windows NT 4.0 (Service Pack 5)
  • Windows 98 / Windows Me
  • Windows 95

您将在其中应用兼容 shims 的 schmorgasboard,Windows 将模拟旧的未记录行为,以帮助您的应用在依赖于该未记录行为时崩溃。

example of compatibility shims that Windows 7 will provide 用于在 Windows Vista 上下文中运行的应用程序:

  • RPC 将使用旧的私有线程池,而不是 OS 线程池
  • 您将能够锁定主视频桌面显示缓冲区
  • 您将能够Blit 到主桌面视频缓冲区,而无需指定剪辑窗口
  • 您将容易受到 GetOverlappedResult 竞争条件的影响(如果您依赖它)
  • 您将继续获得程序兼容性助手 (PCA) 缓解措施

再一次,为了在 Windows 7 下正确测试我的应用程序,我必须添加 supportsOS 清单条目。但是,我不会再次发布带有该标志的应用程序,因为我不想失去这些垫片的好处(例如 PCA)。再说一次,如果某个应用因为在 Vista 上下文中运行而出现了已修复的问题:我永远不会从我们的客户那里知道这件事 - 因为该应用正在运行。


想法?指导?最佳做法?

【问题讨论】:

  • 这是一个很好的问题。
  • 如果您离开清单 (asinvoker),那么您将不会收到问题通知。 Windows 只会调用它的 UAC 启发式算法并静默地使用虚拟文件夹和虚拟注册表配置单元来满足您应用程序的错误请求。如果您尝试超过安全等级,AsInvoker 实际上会导致您的应用程序出错 - 因此您实际上可以找到并调试它。你的概念倒退了,AFAICT
  • Mordachai:是的,这就是我(认为)我的问题所说的。如果我没有清单,Windows 将解决问题。如果我添加清单,启发式被禁用。
  • "为了让我测试这个,我需要将它显示为 Invoker。"我在测试时显示它,以便我看到错误(因为启发式被禁用)。 “我不会以 Invoker 的形式向客户发布应用程序。如果我确实错过了什么,我不希望用户受到影响。”我拿走了清单条目以供发布。

标签: windows manifest compatibility shim


【解决方案1】:

我不会以 Invoker 的形式向客户发布应用程序。如果我确实错过了什么,我不希望用户受到影响。

我认为这是一个不好的方法。我的建议是从一开始就正确体现并测试您部署的内容。

微软不会为了每个人的兼容性而向后弯腰。他们将针对最大的供应商所犯的最常见、影响最大的错误。如果您错过了一些小问题,那么他们将来提供 shim 的机会很小。

每次 Microsoft 添加兼容性填充程序时,我们都付出了代价。有些 API 无法按应有的方式工作,因为它们必须以脑残的方式处理某些情况,以实现与其他人的错误的兼容性。这意味着漫长而痛苦的调试会话,这意味着要阅读更长(或更不完整)的文档,这意味着每个人的操作系统几乎没有效率低下。这也意味着 Windows 开发人员正在浪费时间修复其他人的错误,而不是改进操作系统。

有时,这些兼容性更改是对做对的开发人员的大锤。许多应用程序不能正确处理高 DPI,因此——以兼容性的名义——Vista 假定没有应用程序正确处理它(除非它们明确声明另有说明)。 Vista 应用 UI 缩放。不处理高 DPI 的应用程序得到了改进(但次优)的结果。 确实处理 high_DPI 的应用程序会得到降级的结果。 (而使用好应用程序的客户在升级到 Vista 时会发现它们变得更糟,并责怪微软。)没有缴纳税款的开发人员得到了微软的帮助,而我们其他人(包括微软)则受到了惩罚。避免这种情况的唯一方法是让每个人都缴纳税款。

总体而言,Microsoft 在使这些兼容性填充程序更具针对性方面做得越来越好(尽管 Vista 相当生硬)。然而,每个人都有一点成本。

在开发过程中遵循最佳实践。测试您计划部署的内容。如果它坏了,微软可能会为你修复它。否则,您可能必须发布更新。这比因为一些开发人员没有做正确的事情而受到惩罚的每个人都要好。

【讨论】:

  • 我同意你所说的一切。但是,如果软件由于我特别选择的功能而崩溃 - 那么我就破坏了它。我认为 Windows 不应该有 shims,我认为应用程序应该崩溃,并且公司需要为所有用户免费修复它们。如果公司不想更新,公司丢失了源代码,或者公司不存在,那么仍然需要有人修复它。
【解决方案2】:

AsInvoker 是分发应用程序的正确方法!!!

所有这些都是使用用户的凭据运行的。它没有说“偷偷摸摸”或“使用管理员权限”。

如果没有该清单,您会将您的应用程序标记为“我不了解 UAC,因此请提供您需要的任何技巧,以使我仍然可以在任何具有 UAC 的系统上运行”

但是,如果您的应用程序不尝试仅执行管理员操作 - 并且您可以通过简单地以标准用户身份登录然后运行您的应用程序并观察故障来轻松测试 - 那么 AsInvoker 是绝对正确的。

这可能会帮助您掌握它:A Programmer's Exploration of Vista's User Account Control

【讨论】:

  • 我的应用程序不会(有意)执行任何仅限管理员操作的操作。几乎所有应用程序也是如此。这就是为什么许多应用程序在作为真正的标准用户运行时会失败的原因。这就是微软在 Vista 上创建标准用户启发式的原因。
  • "您可以通过简单地以标准用户身份登录然后运行您的应用程序并观察故障来轻松测试" 这不是真的;没有那么容易”。有些有时难以到达我自己的测试可能永远看不到的代码路径。如果这很容易,那么所有程序都不会出现错误,因为每个可能的场景都已经过测试。
  • 最后,请特别注意我最初的问题中的一行,“如果我确实错过了一些东西......”。如果我确实错过了什么,我想申请继续工作。毕竟,它在 XP 中工作 - 但突然在 Vista 中失败了。客户说“愚蠢的 Vista”。突然间,客户拒绝升级到 Vista,因为“它破坏了我们重要的业务应用程序。”
  • 我确实听到您在说什么:理想情况下,您希望 MS 使用它可以提供的任何兼容性垫片,以确保您的应用程序在任何新版本上继续无忧运行他们制作的操作系统(或服务包)。但是,UAC 启发式方法使许多程序在难以理解并以正确的方式运行时失败。由于 MS 的兼容性垫片以及虚拟化注册表和文件系统的工作方式,我不得不支持许多遗留应用程序的用户,这些应用程序无法正常工作。将您的应用程序标记为 pre-Vista 并不能将您与问题隔离开来
  • 它只是改变了您面临的问题。简单的例子:一个程序将设置存储在 HKLM\Software\company\... 这在 XP 等下工作。用户升级到 Vista。软件继续运行并显示他当前的设置...直到用户更改设置。此时,软件尝试写入 HKLM\Software\company\... 并且 UAC 虚拟化介入 - 为应用程序创建一个新的虚拟化密钥,它写入,现在这是应用程序可以看到的唯一密钥在那个地址(所有其他相关设置都“消失”了,因为现在隐藏在虚拟键后面。
【解决方案3】:

据我了解,除了在您的发行版中提供清单文件外,还可以通过将以下命令添加到您的应用程序的资源文件中,将它直接链接到您的 EXE 文件:[1,2]。

CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "YourApp.exe.manifest"

包含 EXE 文件的目录中的单独清单文件可以覆盖此链接清单,但这取决于客户。你不会提供它。

现在,来自 Microsoft 的“RC”资源编译器接受预处理器指令,例如 #ifdef [3]。这意味着,您可以指示您的 Visual Studio 有两个单独的构建目标,定义不同的预处理器定义,例如 TESTING 和 DEPLOYMENT。

然后,只需使用#ifdef 指令为您的测试和部署构建目标使用两个不同的清单文件,您可以根据需要编辑清单文件。这能解决你的问题吗?

[1]http://msdn.microsoft.com/en-us/library/ms997646.aspx
[2]http://doc.ddart.net/xmlsdk/htm/sdk_dependencies_5wvi.htm
[3]http://msdn.microsoft.com/en-us/library/aa381033%28VS.85%29.aspx

【讨论】:

  • 我想到了外部清单。但从 Windows Server 2003 及更高版本开始,任何内部清单都优先于 .manifest 文件 (blogs.msdn.com/junfeng/archive/2009/05/11/…)
  • 这甚至是个好消息,因为我上面描述的解决方案是通过内部清单实现的,不是外部清单。恐怕我不够清楚..我应该解释得更好吗?
  • 一个单独的清单文件,在包含 EXE 文件的目录中,不能覆盖链接的清单。我应该能够添加一个不包括清单的定义,从而使软件使用外部清单。
  • 确实,你是对的:另一种方法是使用#ifdef 在内部清单和 NO 清单之间进行选择,即外部清单,而不是在两个内部清单之间进行选择。效果是一样的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-27
相关资源
最近更新 更多