如何检测Windows10S?

How to detect Windows 10 S?

Windows 10 S 是一个特殊的 Windows 版本,即 streamlined for security and superior performance。基本上你只能从 Microsoft Store 安装应用程序。

您可以通过桌面桥将普通桌面应用程序交付到应用商店,这样本身就不是什么大问题。但是 Windows 10 S 对商店应用施加了额外的限制,这可能会导致它们在启动期间崩溃。

我已收到商店申请审核结果的反馈。

App Policies: 10.1.2.1 Inaccurate Functionality: Windows 10S

Notes To Developer:

Your app doesn't work on Windows 10 S and the application terminates without notice to the user. Apps that don’t work on Windows 10 S must support graceful shutdown.

Steps to reproduce: 1. Launch the app on Windows 10S. 2. Notice that your app doesn't work on Windows 10 S and the application terminates without notice to the user.

Please be sure to test your app for Windows 10 S: https://docs.microsoft.com/windows/uwp/porting/desktop-to-uwp-test-windows-s Tested Devices: Windows 10 Desktop

所以基本上我需要做的是检测 Windows 10 S 并通知用户它不受支持。

使用 GetProductInfo Win32 API 调用并检查 return 值 PRODUCT_CLOUD (0x000000B2) 和 PRODUCT_CLOUDN (0x000000B3).这 2 个值是 Windows 10 S.

的 SKU 检测代码

我只是把它扔在那里,作为一个替代想法。这完全没有记录!

我纯属偶然了解到,如果您尝试 ShellExecuteEx 10 S 中不允许的 Windows 默认应用程序之一,例如 %WinDir%\System32\cmd.exe,它将失败并显示错误代码 ERROR_SYSTEM_NEEDS_REMEDIATION(或 15623),我还没有看到从任何其他调用返回的错误代码。

受到 magicandre1981 检查 SKU 的解决方案的启发,我将其实现为一个具体的解决方案。它包含 GetVersionEx() 在 Windows 10 中被弃用的解决方法,它包含对 Windows 10 S 开发模式的检查,以便进行适当的测试。

一个免责声明是此检查在我的环境(真实 10 S 和开发模式)中按预期工作。但是最终用户报告说检查不可靠,我无法验证最终用户是否真的 运行 10 S 或者只是认为他这样做。不过它通过了 Microsoft 的审查程序。

运行检查的 C++ 控制台应用程序示例:

// Windows10SCheck.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

#include "pch.h"
#include <iostream>
#include <Windows.h>

// Function to get the OS version number
//
// Uses RtlGetVersion() is available, otherwise falls back to GetVersionEx()
//
// Returns false if the check fails, true if success
bool GetOSVersion(OSVERSIONINFOEX* osversion) {
    NTSTATUS(WINAPI *RtlGetVersion)(LPOSVERSIONINFOEX);
    *(FARPROC*)&RtlGetVersion = GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion");

    if (RtlGetVersion != NULL)
    {
        // RtlGetVersion uses 0 (STATUS_SUCCESS)
        // as return value when succeeding
        return RtlGetVersion(osversion) == 0;
    }
    else {
        // GetVersionEx was deprecated in Windows 10
        // Only use it as fallback
#pragma warning(suppress : 4996)
        return GetVersionEx((LPOSVERSIONINFO)osversion);
    }
}

// Function to check if the product type is Windows 10 S
//
// The product type values are from: 
//
// Output parameter bool iswin10s indicates if running 10 S or not
//
// Returns false if the check fails, true if success
bool IsWindows10S(bool *iswin10s) {
    OSVERSIONINFOEX osinfo;
    osinfo.dwOSVersionInfoSize = sizeof(osinfo);
    osinfo.szCSDVersion[0] = L'[=10=]';

    if (!GetOSVersion(&osinfo)) {
        return false;
    }

    DWORD dwReturnedProductType = 0;

    if (!GetProductInfo(osinfo.dwMajorVersion, osinfo.dwMinorVersion, 0, 0, &dwReturnedProductType)) {
        return false;
    }

    *iswin10s = dwReturnedProductType == PRODUCT_CLOUD || dwReturnedProductType == PRODUCT_CLOUDN;

    return true;
}

bool IsWindows10SDevMode() {
    // Checks for the policy file mentioned in the docs:
    // https://docs.microsoft.com/en-us/windows/uwp/porting/desktop-to-uwp-test-windows-s
    struct stat buffer;

    // x64 applications
    std::string filePathName64 = "C:\Windows\system32\CodeIntegrity\SIPolicy.P7B";
    if (stat(filePathName64.c_str(), &buffer) == 0) {
        return true;
    }

    // x86 applications
    std::string filePathName86 = "C:\Windows\sysnative\CodeIntegrity\SIPolicy.P7B";
    if (stat(filePathName86.c_str(), &buffer) == 0) {
        return true;
    }


    return false;
}

int main() {
    bool is10s = false;
    if (!IsWindows10S(&is10s)) {
        std::cout << "Windows 10 S check failed";
    }

    std::cout << "\nIs 10 S: " << (is10s ? "true" : "false");
    std::cout << "\nIs 10 S Dev Mode: " << (IsWindows10SDevMode() ? "true" : "false");
}

如果 Windows 10 1803 或更新版本,请检查以下 DWORD 注册表值:

  • 注册表项(路径):HKLM\System\CurrentControlSet\Control\CI\Policy
  • 注册表值名称:SkuPolicyRequired
  • 注册表值 (DWORD):1

(来源:https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/microsoft-windows-codeintegrity-skupolicyrequired

在 1803 之前的 Windows 10 版本上,Windows 10 S(和 Windows 10 S N)是他们自己的 SKU。要检查这一点,请使用 WMI 查询以下内容: Win32_OperatingSystem -> 操作系统SKU 并查找整数值 178 (Windows 10 S) 或 179 (Windows 10 S N).

不管 Windows 10 是哪个版本 运行,查询 S 模式 / Windows 10 S / Windows 10 S N 是棘手的,因为常用工具如 cmd 、powershell、regedit、reg、wmic 和 wbemtest 将被阻止。要启用这些工具,需要通过放置注册表项(使用 WinPE 离线)将设备置于制造模式,然后启动计算机。参考:https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/windows-10-s-manufacturing-mode

假设设备处于制造模式并且您可以访问命令提示符,这里有几种查询 S 模式的方法 / Windows 10 S / Windows 10 号 N:

对于 Windows 10 1803 和更新版本,查询 S 模式的简单方法是在命令提示符下键入以下内容:

reg query HKLM\SYSTEM\CurrentControlSet\Control\CI\Policy /v SkuPolicyRequired

(如果您收到 系统无法找到指定的注册表项或值 的消息,或者如果您收到 REG_DWORD 除了 0x1,则 S 模式 未启用 )

对于 1803 之前的 Windows 10 版本,在命令提示符下查询它的一种简单方法是键入:

wmic os get operatingsystemsku