如何以编程方式从 .NET 中的注册表中删除 Windows 产品密钥?

Posted

技术标签:

【中文标题】如何以编程方式从 .NET 中的注册表中删除 Windows 产品密钥?【英文标题】:How to programatically remove the Windows product key from registry in .NET? 【发布时间】:2017-11-01 22:45:33 【问题描述】:

如何以编程方式从 .NET(C# 或 VB.NET)中的注册表中删除 Windows 产品密钥,以重现与使用 @ 调用 Microsoft 的合法 slmgr.vbs 脚本文件时相同的效果987654323@ 参数?...所以请不要在我的问题中将“删除”误解为“卸载”。我只想删除与在HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion:DigitalProductId 注册表值中存储和编码的 Windows 产品密钥相对应的字节,因此产品密钥仍然安装,但对于像 ProduKey 这样的第三方应用程序来说,它变得无法访问.

我试图检查 slmgr.vbs 脚本文件(存储在 C:\Windows\System32),它引导我进入这个方法块:

Private Sub ClearPKeyFromRegistry()
    Dim objService

    On Error Resume Next

    set objService = GetServiceObject("Version")
    QuitIfError()

    objService.ClearProductKeyFromRegistry()
    QuitIfError()

    LineOut GetResource("L_MsgClearedPKey")
End Sub

但是我有点迷失在试图找到并理解 GetServiceObject("Version") 调用的来源和作用,因为它似乎不是内置的 VBS 成员,也不是它似乎不是在脚本文件中声明为任何本地成员,我在 MSDN 文档/VBS 参考上没有找到任何有关“GetServiceObject”的信息。

PS:请注意,我不会依赖 slmgr.vbs 文件的存在来解决此问题,只需从 C# 调用该脚本文件...

更新

我刚刚在Windows文件系统的dll文件中扫描了字符串“ClearProductKeyFromRegistry”,在sppwmi.dll文件中找到了,可惜函数没有导出,然后在 Google 上进行简单的研究,它会将我带到 MSDN 上的 ClearProductKeyFromRegistry method of the SoftwareLicensingService class,但现在我不知道如何使用它。我试图找到有关如何在 .NET 中使用现有 WMI 提供程序的信息,但我在 WWW 上看到的所有信息都是关于如何实现/创建 WMI 提供程序的。

【问题讨论】:

【参考方案1】:

在同一个脚本中,您将找到GetServiceObject 方法(以及它使用的常量和全局变量)。要找到它们,请在脚本中搜索以下术语:

函数获取服务对象 服务类 = g_objWMIService = L_MsgClearedPKey =

所以这只是跟踪代码和转换行的问题。以下是我为该方法的完整 VBScript 版本及其依赖项提出的内容:

private const L_MsgClearedPKey = "Product key from registry cleared successfully."
private const ServiceClass = "SoftwareLicensingService"

g_strComputer = "."
Set g_objWMIService = GetObject("winmgmts:\\" & g_strComputer & "\root\cimv2")

Private Sub ClearPKeyFromRegistry()  
    Dim objService

    On Error Resume Next

    set objService = GetServiceObject("Version")
    QuitIfError()

    objService.ClearProductKeyFromRegistry()
    QuitIfError()

    LineOut GetResource("L_MsgClearedPKey")
End Sub

Function GetServiceObject(strQuery)
    Dim objService
    Dim colServices

    On Error Resume Next

    Set colServices = g_objWMIService.ExecQuery("SELECT " & strQuery & 
        " FROM " & ServiceClass)
    QuitIfError()

    For each objService in colServices
        QuitIfError()
        Exit For
    Next

    QuitIfError()

    set GetServiceObject = objService
End Function

下一步是将其简化为一种方法。我继续删除所有QuitIfError() 调用和On Error Resume Next,因为我们可以将代码包装在try/catch 块中。在替换了常量和全局变量,并结合了这些方法之后,我想出了这个:

Dim objService
Dim colServices
Dim g_objWMIService

Set g_objWMIService = GetObject("winmgmts:\\.\root\cimv2")
Set colServices = g_objWMIService.ExecQuery("SELECT Version FROM SoftwareLicensingService")

For each objService in colServices
    Exit For
Next

objService.ClearProductKeyFromRegistry()

LineOut "Product key from registry cleared successfully."

现在,由于我们使用的是 WMI,我们需要引用 system.management 程序集并添加一个 using:

using System.Management;

然后这只是转换的问题。其中一些我以前没有做过,但它应该可以解决问题:

private static void ClearProductKeyFromRegistry()

    const string query = "SELECT Version FROM SoftwareLicensingService";
    var searcherProd = new ManagementObjectSearcher("\\\\.\\ROOT\\cimv2", query);
    var results = searcherProd.Get();

    foreach (ManagementObject result in results)
    
        result.InvokeMethod("ClearProductKeyFromRegistry", null);
        break;
    

    Console.WriteLine("Product key from registry cleared successfully.");

【讨论】:

【参考方案2】:

最后我发现了调用方法的方法,见 this example。然后我只是按照我在那里看到的内容进行调整,使其适应我的需要,所以我编写了这个用 VB.NET 开发的有用代码 sn-p:

''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Removes the Windows product key from registry (to prevent unauthorized diffusion). 
''' <para></para>
''' It does not uninstall the product key.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <remarks>
''' <see href="https://msdn.microsoft.com/en-us/library/cc534586(v=vs.85).aspx"/>
''' </remarks>
''' ----------------------------------------------------------------------------------------------------
''' <exception cref="PlatformNotSupportedException">
''' Windows 7 or newer is required to use this feature.
''' </exception>
''' 
''' <exception cref="Exception">
''' Unknown error occurred during the product key removal attempt.
''' </exception>
''' ----------------------------------------------------------------------------------------------------
<DebuggerStepThrough>
Public Shared Sub RemoveWindowsProductKeyFromRegistry()

    ' If Not (WindowsUtils.IsWin7OrGreater) Then
    '     Throw New PlatformNotSupportedException("Windows 7 or newer is required to use this feature.")
    ' End If

    Using query As New ManagementObjectSearcher("SELECT * FROM SoftwareLicensingService")

        For Each product As ManagementObject In query.Get()

            Dim result As UInteger
            Try
                result = CUInt(product.InvokeMethod("ClearProductKeyFromRegistry", Nothing))

            Catch ex As COMException
                Marshal.ThrowExceptionForHR(ex.HResult)

            Catch ex As Exception
                Throw

            End Try

            If (result <> 0UI) Then
                Throw New Exception("Unknown error occurred during the product key removal attempt.")
            End If

        Next product

    End Using

End Sub

加上这个其他 sn-p 带来了一种以编程方式安装产品密钥的方法(它可以在我的装有 Windows 10 的机器上运行,但可能需要更多测试):

''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Installs a Windows product key.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <remarks>
''' <see href="https://msdn.microsoft.com/en-us/library/cc534590(v=vs.85).aspx"/>
''' </remarks>
''' ----------------------------------------------------------------------------------------------------
''' <example> This is a code example.
''' <code>
''' Dim productKey As String = "YTMG3-N6DKC-DKB77-7M9GH-8HVXX"
''' InstallProductKey(productKey)
''' </code>
''' </example>
''' ----------------------------------------------------------------------------------------------------
''' <param name="productKey">
''' The product key.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <exception cref="PlatformNotSupportedException">
''' Windows 7 or newer is required to use this feature.
''' </exception>
''' 
''' <exception cref="ArgumentNullException">
''' productKey
''' </exception>
''' 
''' <exception cref="Exception">
''' The Software Licensing Service determined that the product key is invalid.
''' or
''' Unknown error occurred during the product key installation attempt.
''' </exception>
''' ----------------------------------------------------------------------------------------------------
<DebuggerStepThrough>
Public Shared Sub InstallProductKey(ByVal productKey As String)

    ' If Not (WindowsUtils.IsWin7OrGreater) Then
    '     Throw New PlatformNotSupportedException("Windows 7 or newer is required to use this feature.")
    ' End If

    Using query As New ManagementObjectSearcher("SELECT * FROM SoftwareLicensingService")

        For Each product As ManagementObject In query.Get()

            Dim result As UInteger
            Try
                result = CUInt(product.InvokeMethod("InstallProductKey", productKey))
                product.InvokeMethod("RefreshLicenseStatus", Nothing)

            Catch ex As COMException When (ex.HResult = -1073418160)
                Throw New Exception("The Software Licensing Service determined that the product key is invalid.", ex)

            Catch ex As COMException
                Marshal.ThrowExceptionForHR(ex.HResult)

            Catch ex As Exception
                Throw

            End Try

            If (result <> 0UI) Then
                Throw New Exception("Unknown error occurred during the product key installation attempt.")
            End If

        Next product

    End Using

End Sub

【讨论】:

以上是关于如何以编程方式从 .NET 中的注册表中删除 Windows 产品密钥?的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式检查 .NET 中的有效删除(修改)或写入权限?

如何以编程方式从 Python 中的融合模式注册表中获取模式

如何以编程方式删除 Excel 工作表 VB.NET

如何以编程方式从ios中的照片中删除图像?

如何在android中以编程方式从收件箱中删除所有短信?

如何以编程方式从 Android 的默认应用列表中删除应用?