【问题标题】:Determining if the program is running on Windows Server确定程序是否在 Windows Server 上运行
【发布时间】:2011-03-09 11:21:47
【问题描述】:

我想确定我的程序是否在某个版本的 Windows Server 上运行。显然,System.Environment 不包含有关 Windows 是服务器版本这一事实的信息(OS version object 中没有此类信息)。

我知道我可以使用SystemInformation.TerminalServerSession 来检查我的程序是否在远程桌面上运行(另请参阅this question),但如果用户只是远程访问普通客户端 Windows 机器,这也是正确的。

那么是否有一种受支持的方式来确定代码是在服务器上还是在客户端计算机上运行?如果需要,我不介意使用 P/Invoke。

注意:我不想在产品名称中搜索"Server" 字符串,因为由于本地化,这可能不适用于某些系统。

【问题讨论】:

    标签: c# windows-server


    【解决方案1】:

    感谢尼克的回答提供的指示,我终于找到了我要找的东西。函数IsOS(OS_ANYSERVER) 正是我所需要的。这是适用于任何操作系统版本的示例代码(包括Vista之前的版本,因为我们从shlwapi.dll按序号导入IsOS函数):

    class OS
    {
        public static bool IsWindowsServer()
        {
            return OS.IsOS (OS.OS_ANYSERVER);
        }
    
        const int OS_ANYSERVER = 29;
    
        [DllImport("shlwapi.dll", SetLastError=true, EntryPoint="#437")]
        private static extern bool IsOS(int os);
    }
    

    【讨论】:

    • 如果 nick 给了您用来获取所需信息的答案,那么您应该接受该答案而不是您自己的答案(此处的信息应在您的问题中进行编辑)。
    • 好吧,Nick 没有提供 IsOS 解决方案。因此,其他读者将我自己的答案标记为已接受的答案似乎更有用。我给尼克投了赞成票。
    • 这是一个很好的答案,感谢您的帮助。另外,当我必须调用外部方法时,我总是使用一个非常好的站点:pinvoke.net 这是 IsOS 方法:pinvoke.net/default.aspx/shlwapi/IsOS.html
    【解决方案2】:

    您可以 p/调用以下 Win32 函数:

    GetProductInfo 适用于 Vista/Windows Server 2008+
    GetVersionEx 适用于 Windows 2000+

    BJ Rollison 在他的博客上有关于此的 good postsample code

    【讨论】:

    • 感谢您的链接。我终于通过调用 IsOS 解决了这个问题。
    【解决方案3】:

    IsWindowsServerVersionHelpers.h 中的一个内联函数。

    您可以在计算机上找到并读取该头文件。它使用API​​函数VerifyVersionInfoW

    kernel32.dll 中没有函数IswindowsServer

    【讨论】:

      【解决方案4】:

      我遇到了同样的问题,尽管是在脚本中。

      我找到了这个值;我正在使用 WMI 查询它:

      https://msdn.microsoft.com/en-us/library/aa394239(v=vs.85).aspx
      Win32_OperatingSystem
      ProductType
          Data type: uint32
          Access type: Read-only
          Additional system information.
          Work Station (1)
          Domain Controller (2)
          Server (3)
      

      我针对以下操作系统版本对此进行了测试:

      • Windows XP 专业版 SP3
      • Windows 7 企业版
      • Windows 8.1 专业版
      • Windows 8.1 企业版
      • Windows 10 专业版 10.0.16299
      • Windows Server 2003 R2 标准版
      • Windows Server 2003 R2 标准版 x64
      • Windows Server 2008 R2 标准版
      • Windows Server 2012 数据中心
      • Windows Server 2012 R2 数据中心

      在下面找到我的示例批处理文件。

      卢卡斯。

      for /f "tokens=2 delims==" %%a in ( 'wmic.exe os get producttype /value' ) do (
          set PRODUCT_TYPE=%%a
      )
      if %PRODUCT_TYPE%==1 set PRODUCT_TYPE=Workstation
      if %PRODUCT_TYPE%==2 set PRODUCT_TYPE=DomainController
      if %PRODUCT_TYPE%==3 set PRODUCT_TYPE=Server
      echo %COMPUTERNAME%: %PRODUCT_TYPE%
      

      您可以在 C# 中轻松做到这一点:

      using Microsoft.Management.Infrastructure;
      ...
      string Namespace = @"root\cimv2";
      string className = "Win32_OperatingSystem";
      
      CimInstance operatingSystem = new CimInstance(className, Namespace);
      

      【讨论】:

        【解决方案5】:

        应该在程序集 Kernel32.DLL 的 WinAPI 的 VersionHelpers.h 头文件中定义了一组“版本帮助程序函数”。根据文档,应该适用于您的情况的是 IsWindowsServer(void)。说明在这里:

        http://msdn.microsoft.com/en-us/library/windows/desktop/dn424963%28v=vs.85%29.aspx

        在 c# 中,代码如下(未经测试):

        using System.Runtime.InteropServices;
        
        public static class MyClass
        {
            [DllImport("Kernel32.dll")]
            public static extern Boolean IsWindowsServer();
        }
        

        然后消费代码就是:

        bool is_it_a_server = MyClass.IsWindowsServer();
        

        我从来没有使用过这些功能,所以请告诉我它是如何工作的......

        【讨论】:

        • 当我将 Kernel32.dll 或 Ntdll.dll 用于 DllImport 时,我收到一个错误,即在这些程序集中找不到 IsWindowsServer()。
        • 见 Paul Hoepping 的回答;他解释了为什么在kernel32.dll 中找不到IsWindowsServer
        • 此功能不可互操作请务必查看此站点pinvoke.net,这对我每次都有很大帮助。
        最近更新 更多