使用InstallShield制作Windows阿里云Virtio驱动安装包(二)--针对2016系统的特殊处理

时间:2021-01-25 04:43:32

    在上一篇打包阿里云驱动的文章中,文章的最后留下了一个疑问,如何针对2016系统放文件。尝试了很多种方式。

    1.最开始想着InstallShield有一个结构体叫SYSINFO,天真的以为可以利用SYSINFO.nWinMajor和SYSINFO.nWinMinor,或者SYSINFO.nOSMajor和SYSINFO.nOSMinor判断系统内核版本是不是大于6.3,或者说等于10.0。于是乎有了以下的InstallScript代码:

//调试打印输出用
Sprintf(systemWinVersion, "nWinMajor is = %d , nWinMinor is = %d .", SYSINFO.nWinMajor, SYSINFO.nWinMinor);
Sprintf(osWinVersion , "osMajor is = %d , osMinor is = %d .", SYSINFO.nOSMajor, SYSINFO.nOSMinor);
MessageBox(systemWinVersion,WARNING);
MessageBox(osWinVersion,WARNING);

//如何MajorVersion等于10,则为2016系统
if(SYSINFO.nWinMajor == 10) then
	InstallAllSys2016Drivers();
else 
	InstallAllDrivers();
endif;

    但是很不幸的是,无论是systemWinVersion还是osWinVersion对于2016系统输出的都是6.3,即和2012R2系统一致。曾经一度以为自己装了一个假的2016系统。再来,发现InstallShield功能还是很强大的,可以使用自家的UseDLL API直接调用dll动态库,然后使用dll中的函数,在查阅MSDN的过程中,发现微软的Kernel32有两个API函数用来判断操作系统版本,分别是IsWindows10OrGreater和IsWindowsVersionOrGreater。于是乎又有了下面的InstallScript代码:

#define DLL_FILE "Kernel32.dll"

prototype Kernel32.IsWindows10OrGreater();
prototype Kernel32.IsWindowsVersionOrGreater(SHORT,SHORT,SHORT);

nResult = UseDLL(DLL_FILE);
if(nResult = 0) then
	MessageBox("Successfully use Kernel32.dll",SEVERE);
else
	MessageBox("Failed use Kernel32.dll",SEVERE);
endif;

if(IsWindowsVersionOrGreater(10,0,0)) then
	MessageBox("This is Windows 2016", SEVERE);
	InstallAllSys2016Drivers();
else
	MessageBox("This is not Windows 2016", SEVERE);
	InstallAllDrivers();
endif;

if(UnUseDLL(DLL_FILE) < 0) then
	MessageBox("UnuseKernel32 failed ", SEVERE);
else
	MessageBox("UnuseKernel32 Successful ", SEVERE);
endif;

    代码似乎又跟我开了一个玩笑,这两个API依然无法判断系统是否为2016,继续浏览MSDN,发现一个GetVersionEx函数,下面的描述让我很是拨凉拨凉~~~微软自己在Win10/Server2016里面埋下了一个坑,除非用C++加上manifest文件来实现。不然直接获取系统内核版本号返回的就是Win8/Server2012R2的版本号。

    使用InstallShield制作Windows阿里云Virtio驱动安装包(二)--针对2016系统的特殊处理

    经历了坑之后,就想着这只能使用C++来写个可执行exe来实现这个功能了,后来发现InstallShield还有一个函数叫LaunchAppAndWait,这个函数类似于Windows C++的CreateProcess函数,是InstallShield调用可执行文件的API,但是当时网上对于这个API的描述太少,InstallShield自己的帮助文档也对LaunchAppAndWait的返回值描述的很模糊。当时就想着C++写一个函数,是2016系统返回非0,不是2016系统返回0,这个LaunchAppAndWait的返回值是不是就是可执行程序的返回值。后来自己用C++写了一个判断2016系统的程序,具体C++代码可以参考我的博客《使用WMI获取Windows操作系统内核版本号(C++实现)》,然后InstallScript代码如下: 

if(SYSINFO.bIsWow64) then
	szProgram = "\"" + TARGETDIR^"JudgeSystem2016.exe\""; 
	nResult = LaunchAppAndWait(szProgram,"",nOptions);
	if(nResult = 2) then
		MessageBox("The system is 2016!",INFORMATION);
		InstallAllSys2016Drivers();
	else
		MessageBox("The system is 64 bit system!",INFORMATION);
		InstallAllDrivers();
	endif;
else
	MessageBox("The system is 32 bit system!",INFORMATION);
	InstallAllDrivers();
endif;

    经过了这次尝试我是发现了LaunchAppAndWait这个函数只会返回0跟非0,非0代表执行失败。当时真的非常失望,最后还是打开了cmd窗口,输入了ver命令,发现了惊喜。

    使用InstallShield制作Windows阿里云Virtio驱动安装包(二)--针对2016系统的特殊处理

    这好像可以写一个批处理程序啊,于是说干就干,批处理代码如下:

@echo off

echo 当前路径: %~dp0
ver|findstr /r /i " [版本 10.0.*]" > NUL && goto WindowsServer2016
goto WindowsServerOther

:WindowsServer2016
if exist "%~dp02016SysDriver" (xcopy "%~dp02016SysDriver\*" "%~dp0" /s /e /y /q)
rd /s /Q "%~dp02016SysDriver" >nul 2>nul
goto End

:WindowsServerOther
rd /s /Q "%~dp02016SysDriver" >nul 2>nul

:End
exit
@echo on
    终于,烦人的2016系统特殊处理问题终于解决了,在下一篇文章《使用InstallShield制作Windows阿里云Virtio驱动安装包(三)-- 安装和卸载驱动》中我会描述使用InstallScript代码安装和卸载驱动程序。