如何检测Windows 10 S?

3

Windows 10 S是一个特殊的Windows版本,旨在提高安全性和性能表现。基本上你只能从Microsoft Store安装应用程序。

你可以通过桌面桥接将普通桌面应用程序交付给商店,因此本身并不是一个大问题。然而,Windows 10 S对商店应用程序施加了额外的限制,这可能导致它们在启动时崩溃。

我已经从商店应用程序审核结果中收到了这个反馈。

应用程序政策: 10.1.2.1 功能不准确: Windows 10S

开发者注意事项:

您的应用程序无法在Windows 10S上运行,并且应用程序会在未通知用户的情况下终止。不能在Windows 10S上运行的应用程序必须支持优雅关机。

重现步骤: 1. 在Windows 10S上启动应用程序。 2. 注意到您的应用程序无法在Windows 10S上运行,并且应用程序会在未通知用户的情况下终止。

请务必为Windows 10S测试您的应用程序: https://learn.microsoft.com/windows/uwp/porting/desktop-to-uwp-test-windows-s 测试设备: Windows 10桌面版

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


请查看这个问题。 - Klooven
1
我还添加了没有WMP的N版值,因为您来自波兰,可能会遇到检测此版本的问题。 - magicandre1981
2
你好奇地问一下,你知道你的应用程序是因为什么而崩溃了吗? - Peter Torr - MSFT
1
@PeterTorr-MSFT 我认为这是因为我正在使用System.Diagnostics.Process.Start来启动除我的应用程序之外的进程。此外,这就是package sanity test建议的做法:https://github.com/PawelTroka/Computator.NET/issues/129 - Pawel Troka
啊,是的,在Windows 10 S上无法运行CMD或PowerShell脚本。谢谢! - Peter Torr - MSFT
据我所知,我在我的代码中没有运行CMD或PowerShell(当然,我的库可能会,但我不知道是为了什么)。但是,我确实运行fontview.exe(对字体文件进行Process.Start),资源管理器(对目录路径进行Process.Start)和Web浏览器(对URL进行Process.Start)。 - Pawel Troka
4个回答

7
使用 GetProductInfo Win32 API 调用,并检查返回值 PRODUCT_CLOUD (0x000000B2) 和 PRODUCT_CLOUDN (0x000000B3)。这两个值是 Windows 10 S 的 SKU 检测代码。

这种方法可能很快就会停止使用,因为微软已经宣布他们打算将10S变成一种模式而不是一个独立的产品。如果他们这样做,那么当用户切换该选项时,SKU可能会保持不变。 - jbcarpen
@jbcarpen 我们需要等待最终产品和SDK,看看微软如何为所有SKU实现这种S模式。 - magicandre1981
1
是的,我可以确认,我刚在Win10 S机器上进行的测试中得到的pdwReturnedProductType0xB2 - c00000fd
1
@c00000fd 这是期望的结果。对于版本1803(17133.1),您可以通过在HKLM\System\CurrentControlSet\Control\CI\Policy下创建一个名为WindowsLockdownTrialMode的新DWORD来将任何版本转换为S模式。因此,要检测此模式,请查询该值。 - magicandre1981
此答案不适用于Windows 10 1803及更高版本。有关更多信息,请参见:https://dev59.com/Fqbja4cB1Zd3GeqPnOA0#58685975 - Frank Lesniak
显示剩余5条评论

2
如果使用的是Windows 10 1803或更新版本,请检查以下DWORD注册表值:
  • 注册表键(路径):HKLM\System\CurrentControlSet\Control\CI\Policy
  • 注册表值名称:SkuPolicyRequired
  • 注册表值(DWORD):1
(来源:https://learn.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 -> OperatingSystemSKU 并查找整数值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://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/windows-10-s-manufacturing-mode 假设设备处于制造模式并且您可以访问命令提示符,则有几种方法可以查询S模式/Windows 10 S / Windows 10 S N:
对于Windows 10 1803及更高版本,查询S模式的简单方法是在命令提示符下键入以下内容:
reg query HKLM\SYSTEM\CurrentControlSet\Control\CI\Policy /v SkuPolicyRequired
(如果您收到“系统无法找到指定的注册表键或值”的消息,或者收到一个REG_DWORD结果而不是0x1,则S模式未启用)。
对于早于Windows 10版本1803的版本,在命令提示符下查询此信息的简单方法是键入:
wmic os get operatingsystemsku

2
受magicandre1981的解决方案启发,我将其作为具体解决方案实施。它包含一个解决方案来应对在Windows 10中弃用的GetVersionEx(),并且它包含一个检查Windows 10 S Dev模式以允许正确测试的方法。
一个免责声明是,在我的环境中(真正的10 S和Dev模式),这个检查按预期工作。但是一个最终用户报告说这个检查不可靠,我无法验证最终用户是否真的运行了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: https://dev59.com/Fqbja4cB1Zd3GeqPnOA0#47368738
//
// 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'\0';

    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://learn.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");
}

1

我只是提出一个替代想法。这完全没有记录!

我偶然发现,如果您尝试ShellExecuteEx其中一个不允许在10 S中使用的Windows默认应用程序,例如%WinDir%\System32\cmd.exe,它将失败,并显示错误代码ERROR_SYSTEM_NEEDS_REMEDIATION(或15623),我从未见过其他调用返回此错误代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接