Win32:针对明显应用程序测试与部署的建议
从 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 的客户。 如果我确实错过了某些内容,我不希望用户受到影响。我想要 Microsoft 操作系统来修复我的错误。这个解决方案的问题是:
- 我必须在发布之前修改 manfiest,
- 我永远不会知道我错过的事情,因为它们只在 Windows Vista 上工作。
Windows 7 的支持的操作系统<也出现了类似的难题/strong> 体现整体。您可以向应用程序添加清单,指示您设计和测试的 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
,您将获得应用的兼容性填充程序的 schmorgasboard,Windows 将按顺序模拟旧的未记录的行为帮助您的应用程序在依赖于未记录的行为时崩溃。
Windows 7 将提供的兼容性填充程序示例 对于在 Windows Vista 上下文中运行的应用程序:
- RPC 将使用旧的专用线程池,而不是操作系统线程池,
- 锁定主视频桌面显示缓冲区
- 您将能够 Blit 到主桌面视频缓冲区而不指定剪辑窗口,
- 您将很容易受到 GetOverlappedResult 竞争条件的影响(如果您依赖它),
- 您将继续获得程序兼容性助手 (PCA) 缓解,
并且再次,为了在 Windows 7 下正确测试我的应用程序,我必须添加 supportsOS 清单条目。但是,我再次强调,我不会使用该标志来发布应用程序,因为我不想失去这些垫片(例如 PCA)的好处。而且,如果某个应用程序因在 Vista 上下文中运行而出现问题而得到修复:我永远不会从我们的客户那里得知这一情况 - 因为该应用程序刚刚工作。
想法?指导?最佳实践?
Starting with Windows Vista, Microsoft added a class of compatibility shims that will allow an application that assumes it has administrative file and registry access to continue to function.
In other words: An application that failed on Windows XP would run on Windows Vista.
These OS provided bug-fixes can be disabled by adding a section to the application manifest, declaring the application should run asInvoker
:
<!-- Disable Windows Vista standard user compatability heuristics -->
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker"/>
</requestedPrivileges>
</security>
</trustInfo>
Ideally, a developer would test their application to ensure that it doesn't (needlessly) require administrative privelages. In order for me to test this, i would need to manifest it asInvoker.
But when it comes down to it, i'm not going to release the application to the customer manifested asInvoker. If i did miss something, i don't want the user to be impacted. i want Microsoft's operating system to fix my mistakes. Problem with this solution is:
- i have to modify the manfiest before release
- i'll never know about the things i missed, becuase they're just work on Windows Vista.
A similar conundrum comes up with Windows 7's supportedOS manifiest entires. You can add a manifest to the application indicating which version of Windows you were designed and tested for:
<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>
In the case of the supportedOS items, the operating system knows up front which OS you were designed for. This will place your application in the context of Windows Vista if you do not say that you support Windows 7:
(source: msdn.com)
This action is similar to running an application in some Compatibility Mode, e.g.:
- 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
where you will get a schmorgasboard of compatibilty shims applied, and Windows will emulate old undocumented behaviour in order to help your app from crashing when it depended on that undocumented behaviour.
An example of compatibility shims that Windows 7 will provide for an application running in the Windows Vista context:
- RPC will use the old private thread pool, rather than the OS thread pool
- you will be able to Lock the primary video desktop display buffer
- you will be able to Blit to the primary desktop video buffer without specifying a clipping window
- you will be vulnerable to a GetOverlappedResult race condition (if you depended on it)
- you will continue to get Program Compatibilty Assistant (PCA) mitigation
And once again, in order to test my application properly under Windows 7, i have to add the supportsOS manifest entry. But, again, i'm not going to ship the application with that flag, because i don't want to lose the benefit of these shims (e.g. PCA). And, again, if an app has problems that were fixed because it was running in the Vista context: i'll never know about it from our customers - because the app is just working.
Thoughts? Guidance? Best practices?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我认为这是一个糟糕的做法。我的建议是从一开始就正确地体现并测试您部署的内容。
微软不会为了每个人的兼容性而竭尽全力。他们将针对最大供应商所犯的最常见、影响最大的错误。如果您错过了一些小问题,他们将来提供垫片的机会很小。
每次微软添加兼容性填充程序时,我们都会付出代价。有些 API 无法按应有的方式工作,因为它们必须以一种脑死亡的方式处理某些情况,以实现与其他人的错误的兼容性。这意味着漫长而痛苦的调试过程,意味着需要费力地阅读更长(或不太完整)的文档,并且意味着每个人的操作系统效率都会很低。这也意味着 Windows 开发人员正在浪费时间修复其他人的错误,而不是改进操作系统。
有时,这些兼容性变化是对做得正确的开发人员的惩罚。许多应用程序无法正确处理高 DPI,因此,以兼容性的名义,Vista 假定没有应用程序可以正确处理它(除非它们明确声明不然)。 Vista 应用 UI 缩放。不处理高 DPI 的应用程序会获得改进(但次优)的结果。 确实处理 high_DPI 的应用程序会得到降级的结果。 (使用好的应用程序的客户在升级到 Vista 后发现它们变得更糟并责怪微软。) 不缴纳税款的开发人员会得到微软的帮助,我们其他人(包括微软)会受到惩罚。避免这种情况的唯一方法是每个人都纳税。
总的来说,微软在使这些兼容性垫片更有针对性方面做得越来越好(尽管 Vista 相当直率)。然而,每一项都需要一点成本。
在开发过程中遵循最佳实践。测试您计划部署的内容。如果问题严重,微软可能会为您修复。否则,您可能必须发布更新。这比每个人都因为一些开发者没有做正确的事情而受到惩罚要好。
I think this is a bad approach. My advice is to manifest correctly from the start and test what you deploy.
Microsoft is not going to bend over backwards for everyone's compatibility. They're going to target the most common, high-impact mistakes made by the biggest vendors. If you miss some small issue, the chance of them providing a shim in the future is small.
Every time Microsoft adds a compatibility shim, we all pay a price. There are APIs that don't work the way they should because they had to handle some case in a brain dead way to achieve compatibility with somebody else's bug. This means long, painful debugging sessions, it means wading through longer (or less complete) documentation, and it means little inefficiencies in the OS for everyone. It also means Windows developers are wasting time fixing other people's mistakes instead of improving the OS.
Sometimes these compatibility changes are big hammers that penalize developers who do it right. Many applications don't handle high DPI correctly, so--in the name of compatibility--Vista assumes that no applications handle it correctly (unless they explicitly claim otherwise). Vista applies UI scaling. Applications that didn't handle high-DPI get improved (but suboptimal) results. Applications that did handle high_DPI get degraded results. (And customers who used the good apps see them get worse when they upgrade to Vista and blame Microsoft.) The developers who didn't pay their taxes get help from Microsoft, the rest of us (including Microsoft) get penalized. The only way to avoid this is for everyone to pay their taxes.
In general, Microsoft is getting better at making these compatibility shims more targeted (though Vista was pretty blunt). Nevertheless, there's a little cost to each one.
Follow the best practice during development. Test what you plan to deploy. If it breaks big, Microsoft might fix it for you. Otherwise, you might have to release an update. That's better than everyone suffering a penalty because some developers didn't do the right thing.
AsInvoker 是分发应用程序的正确方法!!!
综上所述,它是使用用户的凭据运行的。它没有说“做一些偷偷摸摸的事情”或“使用管理员权限”。
如果没有该清单,您会将您的应用程序标记为“我不知道 UAC,因此请向我提供您需要的任何技巧,使我仍然可以在任何具有 UAC 的系统上运行”
但是如果您的应用程序不尝试只做管理员的事情 - 你可以通过简单地以标准用户身份登录来轻松测试它然后运行你的应用程序并观察失败 - 那么 AsInvoker 是绝对正确的。
这可能会帮助您掌握它: A Programmer's Exploration of Vista's User帐户控制
AsInvoker is the correct way to distribute your application!!!
All that says, is run with the user's credentials. It doesn't say 'do something sneaky' or 'use admin rights'.
Without that manifest, you're branding your application as "I'm not aware of UAC, so please provide me whatever hacks you need to make me still maybe function on any system that has UAC"
But if your application doesn't try to do admin-only things - and you can easily test that by simply being logged in as a standard user & then running your app and watching for failures - then AsInvoker is absolutely correct.
This might help you get a handle on it: A Programmer's Exploration of Vista's User Account Control
据我了解,您可以通过将以下命令添加到应用程序的资源文件中,将其直接链接到您的 EXE 文件中,而不是在您的发行版中提供清单文件:[1,2]。
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "YourApp.exe.manifest"
包含 EXE 文件的目录中的单独清单文件可以覆盖此链接清单,但这取决于客户。你不会提供它。
现在,Microsoft 的“RC”资源编译器接受预处理器指令,例如#ifdef [3]。这意味着,您可以指示 Visual Studio 有两个单独的构建目标,定义不同的预处理器定义,例如测试和部署。
然后,只需使用 #ifdef 指令即可将两个不同的清单文件用于测试和部署构建目标,并且您可以根据需要编辑清单文件。这能解决您的问题吗?
[1] http://msdn.microsoft.com/en-us/library /ms997646.aspx
[2] http://doc.ddart.net/xmlsdk/htm/sdk_dependency_5wvi.htm
[3] http://msdn.microsoft.com /en-us/library/aa381033%28VS.85%29.aspx
As I understand it, instead of supplying a manifest file with your distribution it can also be linked directly into your EXE file by adding the following command to your application's resource file: [1,2].
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "YourApp.exe.manifest"
A separate manifest file in the directory containing the EXE file could override this linked-in manifest, but that is up to the customer. You wouldn't supply it.
Now, the "RC" resource compiler from Microsoft accepts preprocessor directives such as #ifdef [3]. Which means, you could instruct your Visual Studio to have two separate build targets defining different preprocessor definitions such as TESTING and DEPLOYMENT.
Then, it is just a matter of using #ifdef directives to use two different manifest files for your testing and deployment build targets, and you can edit the manifest files as you wish. Would this solve your problem?
[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