Microsoft Windows 2000 应用程序兼容性 讨论使应用程序在 Microsoft(R) Windows(R) 2000 上存在不兼容性的几个问题。 其中有以下几部分: 介绍 设置和安装问题 Windows 2000 兼容性问题 应用程序稳定性问题 Windows 平台之间的差异 介绍 几个月来,我一直从事一项任务,即找出 Windows 2000 操作系统中的应用程序兼 容性问题。在这里我真正要讨论的是,造成应用程序与 Windows 2000 不兼容的原 因。没有人真正关心使应用程序兼容的原因。 我一直在与 Windows 2000 测试组合作,他们在过去的几个月中已测试了数百个应 用程序。我们已将应用程序在 Windows 2000 上正常或不正常运行的原因进行书面 论述。我们发现的问题可以归为四类: 1.无法在 Windows 2000 上安装的应用程序。 这是迄今我们发现的最大问题。应 用程序在 Windows 2000 上安装的方式并无甚特殊之处;问题是这些应用程序不让 自己安装到这一新版本的操作系统中。 2.我们对操作系统所做的、影响应用程序运行的更改。每当 Microsoft Windows NT(R) 开发组面临选择,是使系统作为平台更稳定或更强大,还是保障应用程序的 兼容性,他们总是牺牲后者而取稳定性。Windows 2000 开发工作的一个主要目标 就是让系统作为平台更加稳定。遗憾的是,为了实现这一点而必须进行的某些改动 ,已导致应用程序在 Windows 2000 上不兼容。 3.我们已对操作系统进行的更改不会影响应用程序的兼容性,但会中断某些应用程序。 4.过于依赖 Windows 9x 平台的应用程序。我们在开发 Windows 2000 时,考虑到 有众多 Windows 9x 用户需要升级,因此对 Windows 9x 应用程序进行了测试,将 它们移植到 Windows 2000 中。我们发现某些应用程序过于依赖 Windows 9x。 设置和安装问题 我们要讨论的第一类问题是设置和安装问题;最常见的问题无疑是无法在 Windows 2000 上安装应用程序。实际上,导致无法安装应用程序的一个最普遍的原因,在 于 Windows 2000 是 Windows NT 的 5.0 版。 测试组以多种方式测试应用程序。他们将应用程序安装在基于 Windows 2000 的系 统中,或者将应用程序安装在 Windows NT 4.0 或 Windows 95 中,然后再将系统 升级到 Windows 2000,以便进行测试。 我们拿来一台未安装任何操作系统的机器后,安装上 Windows 2000,再安装应用 程序,与上述升级的情况相比,前者的兼容性数目要少得多。 版本检查 造成应用程序无法安装在 Windows 2000 上的第一位原因,是它们无法正确处理版 本号。我们发现很多应用程序都进行以下示例代码所做的操作。它们在运行过程中 会调用 GetVersionEX,然后写下一条“if”语句,该语句规定:“如果系统是版 本 3,因为没有新的 Shell,我不能正常运行,所以我可能无法安装。如果系统是 版本 4,我可以进行安装和设置”。问题出在如果系统是版本 5,这一“if”语句 就没有了下文。因为版本号是 5.0,这些应用程序由于自身原因而无法安装,所以 我们发现了一系列这样那样的问题。 if (osvi.dwMajorVersion == 3) { // 请这样做 } else if (osvi.dwMajorVersion == 4) { // 请那样做 } 测试组继续寻找解决方案,并蒙蔽了许多此类应用程序。在早期的编译中,我们能 够采取措施改变 GetVersionEx 的返回值。我们可以改变其返回值,欺骗应用程序 ,告诉它版本号就是 4.0,然后程序就能够继续安装,并正常运行。但有部分应用 程序的设计思想就是不能安装在 Windows 2000 上。对于病毒扫描程序或其他低级 实用程序来说,受限于某一操作系统版本是可以理解的。不过,这些应用程序会显 示消息来说明这一点。我们查找的是那些不能安装或无法正常运行、又根本没有通 知用户的应用程序。 怎样才能正确地检查版本号?在 Windows 2000 中我们将添加一个新的 API: VerifyVersionInfo,这一 API 在运行时将依次检查主版本号、次版本号以及服务 包。如果出现了操作系统的新版本,应用程序仍然能够在其上安装并运行。实际上 应用 VerifyVersionInfo 的选项和方式还有很多,但如果只是检查“要是操作系 统升级了,应用程序该如何处理”这一类问题,您只需调用这三个标志,然后检查 主版本号、次版本号以及服务包。您能够定义以下语句:“我的程序需要运行在 Windows NT 4.0、SP2 上”,然后询问 VerifyVersionInfo“我正在运行的操作系 统是否已达到这一标准?”,该 API 将返回真值或假值。 VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask); 采用这一方式检查版本,就可以符合 Windows 2000 应用程序的规范,其基本思想 是“只要存在新版本的操作系统,就要在新版本上进行安装。” 应用 VerifyVersionInfo 的一个问题是目前该 API 只能在 Windows 2000 平台上 运行。为了检查 Windows 95 等旧平台的版本,您必须应用GetVersionEx。查看以 下示例代码,即可发现它的功能与 VerifyVersionInfo 基本相同:依次检查主版 本号、次版本号以及服务包。 BOOL bIsWindowsVersionOK(DWORD dwMajor, DWORD dwMinor, DWORD dwSPMajor ) { OSVERSIONINFO osvi; // 初始化 OSVERSIONINFO 结构 // ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx((OSVERSIONINFO*)&osvi); // 首先,主版本 if ( osvi.dwMajorVersion > dwMajor ) return TRUE; else if ( osvi.dwMajorVersion == dwMajor ) { // 然后,次版本 if (osvi.dwMinorVersion > dwMinor ) return TRUE; else if (osvi.dwMinorVersion == dwMinor ) { // 对,最好检查一下 Service Pack if ( dwSPMajor && osvi.dwPlatformId == VER_PLATFORM_WIN32_NT ) { HKEY hKey; DWORD dwCSDVersion; DWORD dwSize; BOOL fMeetsSPRequirement = FALSE; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Control\\Windows", 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) { dwSize = sizeof(dwCSDVersion); if (RegQueryValueEx(hKey, "CSDVersion", NULL, NULL, (unsigned char*)&dwCSDVersion, &dwSize) == ERROR_SUCCESS) { fMeetsSPRequirement = (LOWORD(dwCSDVersion) >= dwSPMajor); } RegCloseKey(hKey); } return fMeetsSPRequirement; } return TRUE; } } return FALSE; } // // 此示例适用于 Windows 2000 和更新版本 // BOOL bIsWindowsVersionOK(DWORD dwMajor, DWORD dwMinor, DWORD dwSPMajor ) { OSVERSIONINFOEX osvi; ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); osvi.dwMajorVersion = dwMajor; osvi.dwMinorVersion = dwMinor; osvi.wServicePackMajor = dwSPMajor; // 设置条件掩码。 VER_SET_CONDITION( dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL ); VER_SET_CONDITION( dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL ); VER_SET_CONDITION( dwlConditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL ); // 执行测试。 return VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR,dwlConditionMask); } 首先,需要检查主版本号。如果当前操作系统的主版本号高于所需主版本号,则不 需要进行任何检查,直接向下运行即可。如果主版本号相等,则以同样方式检查次 版本号。最后再检查服务包号。在我们获得发布的某一版本时,就可以说“没关系 ,我们不在乎是 Service Pack 3、4 还是 5”。如果主版本号或次版本号有所增 长,系统同样可以处理。我们查找了所有要检查版本信息的应用程序,发现它们将 分别检查每一组件。它们在运行中会说“噢,主版本号是 5,我只要求 4,不错。 次版本号是 .0,很好,但 Service Pack 是 0,我需要的是 3”。很明显, Windows 2000 还没有推出 SP3,所以这种检查版本信息的方法是错误的。 检查 Windows NT 的版本号时需要注意以下细节:检查版本号和服务包信息的方法 有三种。第一种是获取 GetVersionEx 的返回值,然后检查“szCSDVersion”字符 串。实际的服务包号嵌入在该字符串的某一位置。