【问题标题】:Get Offline Installation ID (Windows 8 or similar)获取离线安装 ID(Windows 8 或类似系统)
【发布时间】:2015-06-21 20:18:52
【问题描述】:

是否可以获得 Windows 离线安装 IDOfflineInstallationId 在 slmgr.vbs 中找到)?

这可以在命令行上实现:

slmgr.vbs /dti

这将返回不带空格或破折号的安装 ID,是否可以在 C# 中检索它? 我希望最终将 ID 的每个块(每个块中有 9 个块,每个块中有 7 个数字)放在表单上自己的文本框中。

有 9 个区块,每个区块有 7 个数字

我环顾四周,但找不到任何 C# 示例。

【问题讨论】:

    标签: c# windows installation


    【解决方案1】:

    这可以通过查询 WMI(Windows 管理规范)的 Win32_WindowsProductActivation(XP 及以下)或 SoftwareLicensingProduct(Vista 或更高)类来实现:

    需要声明这些命名空间:

    • 系统
    • System.Collections.Generic
    • 系统管理
    • System.Text

    使用using 在代码文件的顶部 声明这些命名空间,就其本身而言:

    using System;
    using System.Collections.Generic;
    using System.Management;
    using System.Text;
    

    然后在函数中使用以下代码:

    ManagementScope Scope;
    Scope = new ManagementScope("\\\\.\\ROOT\\cimv2");
    Scope.Connect();
    ObjectQuery Query = new ObjectQuery("SELECT OfflineInstallationId FROM SoftwareLicensingProduct");
    ManagementObjectSearcher Searcher = new ManagementObjectSearcher(Scope, Query);
    foreach (ManagementObject WmiObject in Searcher.Get())
    {
        //Do whatever with the Offline Installation ID here.   
    }
    

    我注意到,因为我使用了一次 Windows 8.1 的“刷新”功能,我的 WMI 为我返回了 两个 脱机安装 ID,因此这应该是您需要考虑的事情(第一个离线安装 ID 是有效的):

    你可能想要类似这样的东西:

    static string getOfflineInstallId()
    {
        ManagementScope Scope;
        Scope = new ManagementScope("\\\\.\\ROOT\\cimv2");
        Scope.Connect();
        ObjectQuery Query = new ObjectQuery("SELECT OfflineInstallationId FROM SoftwareLicensingProduct");
        ManagementObjectSearcher Searcher = new ManagementObjectSearcher(Scope, Query);
    
        foreach (ManagementObject WmiObject in Searcher.Get())
        {
            if (WmiObject["OfflineInstallationId"] != null)
                return WmiObject["OfflineInstallationId"].ToString();
        }
        return ""; //Making the compiler happy.
    }
    

    如前所述,SoftwareLicensingProductOfflineInstallationId 仅适用于比 Vista 更新的 Windows 版本(例如 Vista、7、8、8.1 和 10),因此如果您(或您的程序的用户)希望在 XP 或更早版本上使用它,您也许可以使用以下内容,但是由于我无法访问 XP,因此无法对此进行测试:

    ObjectQuery Query = new ObjectQuery("SELECT GetInstallationID FROM Win32_WindowsProductActivation");
    

    如果你想将ID的每个块分开并插入一个TextBox到一个Windows窗体(WinForm)中,你可以使用下面的代码:

    string installId = getOfflineInstallId();
    StringBuilder sb = new StringBuilder();
    bool fRun = false;
    for (int i = 0; i < installId.Length; i++)
    {
        if (i % 7 == 0)
        {
            if (fRun)
                sb.Append('-');
            else
                fRun = true; //Stops a '-' being added at the 1st position.
        }
        sb.Append(installId[i]);
    }
    idTextBox.Text = sb.ToString();
    

    类似这样的:

    除此之外,您还需要通过在解决方案资源管理器中右键单击 References、单击 Add New Reference 并添加 System.Management 和 @987654339 来引用 System.Management 库@给项目:

    此示例中使用的项目可以在here 下载(需要 Visual Studio 2013 或更高版本)。

    【讨论】:

    • 谢谢你的代码,但我站在管子上。请问您是否可以使代码对我来说更容易一些?我希望这是一个 Windows 窗体 :-)
    • 非常抱歉,我在管子上站了一点。我在 WinForms 中添加了代码,但出现了错误。您是否有我可以看到出了什么问题的项目文件?我绝对是初学者,我只能用 C# 编写简单的东西,但这对我来说太高了 :-( 谢谢你,很抱歉,但你有一个很好的 WinForms 解决方案 :-)
    • @user2422690 “在管子上”是什么意思?究竟是什么错误?查看我的编辑。
    • 我的意思是“在管子上”应该是一句格言(来自一个有格言的网站(德语 -> 英语),我真的不明白在哪里添加代码 :-( 我使用了参考资料在解决方案资源管理器中,项目已被选中并处于活动状态。我收到以下错误:“ManagementScope' 是一个命名空间,但用作类型”。
    【解决方案2】:

    注意,您还应该检查名称或应用程序 ID。 如果你安装了office,你会得到两个或更多的OfflineInstallationId。

    检查名称是否包含Windows 或检查应用程序ID 是否等于55c92734-d682-4d71-983e-d6ec3f16059f

    PS:我不知道不同版本的 Windows 之间的 AppliactionID 是否会发生变化。我做了一些谷歌搜索,发现它似乎是一个静态值。

    【讨论】:

    • 它似乎是静态的。我已经在 Windows 10、Server 2008 R2、Server 2012 R2 和 Server 2016 上进行了测试。所以它可能至少从 7 天以来一直是静态的。
    猜你喜欢
    • 1970-01-01
    • 2012-11-08
    • 1970-01-01
    • 1970-01-01
    • 2019-08-14
    • 2015-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多