如何以编程方式从 .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 中的有效删除(修改)或写入权限?