于是我又开始探索其他思路,在Visual Studio 2010中的环境变量有个方法让我惊喜:System.Environment.Is64BitOperatingSystem,他能够成功的判断操作系统位数,但是失望的是Framework4.0才有这个方法,我们软件目前用的是Framework3.5做平台,只能放弃这个方法了。哎!
在反复尝试中终于又发现一个好方法:Kernel32.dll中的IsWow64Process,具体参考MSDN文档http://msdn.microsoft.com/en-us/library/ms684139(VS.85).aspx
同时看到了一篇很好的文章http://cfx.codeplex.com/SourceControl/changeset/view/39074#,他是先判断IntPtr.S[size=+0]ize 是否是8,很明显,只有64位操作系统才会使int的大小为8位,32位操作系统只能是4位。所以如果Size是8则一定是64位操作系统,但这只是充分非必要条件,如果Size不等于8,我们需要调用Kernel32.dll的IsWow64Process方法来判断:
代码
/// <summary>
/// The function determines whether the current operating system is a
/// 64-bit operating system.
/// </summary>
/// <returns>
/// The function returns true if the operating system is 64-bit;
/// otherwise, it returns false.
/// </returns>
public static bool Is64BitOperatingSystem()
{
if (IntPtr.Size == 8) // 64-bit programs run only on Win64
{
return true;
}
else // 32-bit programs run on both 32-bit and 64-bit Windows
{
// Detect whether the current process is a 32-bit process
// running on a 64-bit system.
bool flag;
return ((DoesWin32MethodExist("kernel32.dll", "IsWow64Process") &&
IsWow64Process(GetCurrentProcess(), out flag)) && flag);
}
}
/// <summary>
/// The function determins whether a method exists in the export
/// table of a certain module.
/// </summary>
/// <param name="moduleName">The name of the module</param>
/// <param name="methodName">The name of the method</param>
/// <returns>
/// The function returns true if the method specified by methodName
/// exists in the export table of the module specified by moduleName.
/// </returns>
static bool DoesWin32MethodExist(string moduleName, string methodName)
{
IntPtr moduleHandle = GetModuleHandle(moduleName);
if (moduleHandle == IntPtr.Zero)
{
return false;
}
return (GetProcAddress(moduleHandle, methodName) != IntPtr.Zero);
}
[DllImport("kernel32.dll")]
static extern IntPtr GetCurrentProcess();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
static extern IntPtr GetModuleHandle(string moduleName);
[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule,
[MarshalAs(UnmanagedType.LPStr)]string procName);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool IsWow64Process(IntPtr hProcess, out bool wow64Process);
既然它能得到,那么我肯定也可以获得啦!~~~在本地搜索slmgr.vbs,找到它后打开,我对VBScript不是很熟,泉哥帮我看了看,虽然他也不熟,但是找东西的速度真是没话说,两三下就找到了最终调用的方法!它是通过slmgr.ini来获取信息的,里面调用了一个方法
Set colServices = g_objWMIService.ExecQuery("SELECT " & strQuery & " FROM " & ServiceClass)
原来他是调用WMI的函数来实现,WMI调用方法参考的http://andrewensley.com/2009/10/c-detect-windows-os-version-%E2%80%93-part-2-wmi/
于是我们的程序就可以这样写了:
代码
internal string OSVersion
{
get
{
if (osVersion == null)
{
var ver = new System.Management.ManagementObjectSearcher("select Version from SoftwareLicensingService");
var items = ver.Get();
foreach (var item in items)
{
object version = item.GetPropertyValue("Version");
osVersion = version.ToString();
}
}
return osVersion;
}
}
这个OSVersion属性就是我们想要的结果!因此第二种方法也就可以实现了!虽然最终我们的程序用的是第一种方法,但是第二种方法的探索过程中得到的一些结果和经验以后很可能会用到,所以还是拿出来与大家分享^_^
经过我测试,Windows Server 2008(32位)、Windows Server 2008 R2(64位) 和 Windows Vista(32位和64位) 系统的IIS安装和Win7的一样!
最后我们需要做的事情就是自动的判断客户机的操作系统,然后选择合适的方法安装!
问题7:如何判断客户机操作系统类型?
回答:参考了MSDN文档http://msdn.microsoft.com/en-us/library/ms724833(VS.85).aspx
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct _OSVERSIONINFOEX
{
public Int32 dwOSVersionInfoSize;
public Int32 dwMajorVersion;
public Int32 dwMinorVersion;
public Int32 dwBuildNumber;
public Int32 dwPlatformId;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
public Char[] szCSDVersion;
public Int16 wServicePackMajor;
public Int16 wServicePackMinor;
public Int16 wSuiteMask;
public Byte wProductType;
public Byte wReserved;
}
/// <summary>
/// 获得OS信息
/// </summary>
class CheckOSInfo
{
[DllImport("kernel32.dll")]
public static extern bool GetVersionEx(ref _OSVERSIONINFOEX osVersionInfo);
[DllImport("user32.dll")]
public static extern int GetSystemMetrics(int sm_SERVERR2);
public static string GetOSName()
{
_OSVERSIONINFOEX osVersionInfo = new _OSVERSIONINFOEX();
osVersionInfo.dwOSVersionInfoSize = 156;
if (GetVersionEx(ref osVersionInfo))
{
switch (osVersionInfo.dwMajorVersion)
{
case 5:
switch (osVersionInfo.dwMinorVersion)
{
case 0:
return "Microsoft Windows 2000";
case 1:
return "Microsoft Windows XP";
case 2:
if ((osVersionInfo.wSuiteMask & 0x00008000) != 0)
return "Microsoft Windows Home Server";
if (osVersionInfo.wProductType == 1 && CheckOSBitness.Is64BitOperatingSystem())
return "Microsoft Windows XP";
if(GetSystemMetrics(89)==0)
return "Microsoft Windows Server 2003";
else
return "Microsoft Windows Server 2003 R2";
}
break;
case 6:
switch (osVersionInfo.dwMinorVersion)
{
case 0:
if (osVersionInfo.wProductType == 1)
return "Microsoft Windows Vista";
else
return "Microsoft Windows Server 2008";
case 1:
if (osVersionInfo.wProductType == 1)
return "Microsoft Windows 7";
else
return "Microsoft Windows Server 2008 R2";
}
break;
}
}
return null;
}
}
最开始两句是调用一个外部DLL的函数的方法。
这样我们就成功的知道了客户所使用的操作系统类型了!
总结一下,Windows 7以前的版本,即包括Windows XP和Windows Server 2003的各个版本的IIS安装,都需要i386文件和配置选项文本文件,其中64位版本的系统还需要AMD64文件,而Windows 7、Windows Vista、Windows Server 2008的IIS安装则只用执行一句命令行就行了。
最终,我们的一键安装IIS程序有一个Source文件夹(里面装有所有版本的i386、amd64以及其他配置文件)和一个我们的程序(获取操作系统类型以及执行一些cmd命令)。