如何以编程方式从 .NET 的注册表中删除 Windows 产品密钥?
How to programatically remove the Windows product key from registry in .NET?
我如何以编程方式从 .NET(C# 或 VB.NET)的注册表中删除 Windows 产品密钥,以重现与调用 Microsoft 的合法 slmgr.vbs 带有 /cpky
参数的脚本文件?...所以请不要误解我的问题 "remove" 为 "uninstall"。我只想删除与 HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion
中存储和编码的 Windows 产品密钥相对应的字节:DigitalProductId
注册表值,因此产品密钥仍然安装但无法访问对于像 ProduKey.
这样的第 3 方应用程序
我试图检查 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 成员,它也不是' t 似乎在脚本文件中被声明为任何本地成员,而且我没有在 MSDN docs/VBS 参考资料中找到任何关于 "GetServiceObject" 的信息。
PS:请注意,我不会依赖 slmgr.vbs 文件的存在来解决这个问题,只需调用该脚本文件即可来自 C#...
更新
我刚刚在 Windows 文件系统的 dll 文件中扫描了字符串“ClearProductKeyFromRegistry”,并在 sppwmi.dll 文件,但不幸的是函数没有导出,然后对 Google 进行简单研究,它引导我到 MSDN 上的 ClearProductKeyFromRegistry method of the SoftwareLicensingService class ,但现在我不知道如何使用它。我试图查找有关如何在 .NET 中使用现有 WMI 提供程序的信息,但我在 WWW 上看到的所有信息都是关于如何 implement/create WMI 提供程序的。
终于找到调用方法的方法了,看this example。然后我只是按照我在那里看到的,根据我的需要进行调整,所以我写了这个在 VB.NET:
中开发的有用的代码片段
''' ----------------------------------------------------------------------------------------------------
''' <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
加上另一个代码片段,以提供一种以编程方式安装产品密钥的方法(它在我的机器上使用 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
在同一个脚本中,您会找到 GetServiceObject
方法(以及它使用的常量和全局变量)。要找到它们,请在脚本中搜索以下术语:
- Function GetServiceObject
- ServiceClass =
- 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.");
}
我如何以编程方式从 .NET(C# 或 VB.NET)的注册表中删除 Windows 产品密钥,以重现与调用 Microsoft 的合法 slmgr.vbs 带有 /cpky
参数的脚本文件?...所以请不要误解我的问题 "remove" 为 "uninstall"。我只想删除与 HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion
中存储和编码的 Windows 产品密钥相对应的字节:DigitalProductId
注册表值,因此产品密钥仍然安装但无法访问对于像 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 成员,它也不是' t 似乎在脚本文件中被声明为任何本地成员,而且我没有在 MSDN docs/VBS 参考资料中找到任何关于 "GetServiceObject" 的信息。
PS:请注意,我不会依赖 slmgr.vbs 文件的存在来解决这个问题,只需调用该脚本文件即可来自 C#...
更新
我刚刚在 Windows 文件系统的 dll 文件中扫描了字符串“ClearProductKeyFromRegistry”,并在 sppwmi.dll 文件,但不幸的是函数没有导出,然后对 Google 进行简单研究,它引导我到 MSDN 上的 ClearProductKeyFromRegistry method of the SoftwareLicensingService class ,但现在我不知道如何使用它。我试图查找有关如何在 .NET 中使用现有 WMI 提供程序的信息,但我在 WWW 上看到的所有信息都是关于如何 implement/create WMI 提供程序的。
终于找到调用方法的方法了,看this example。然后我只是按照我在那里看到的,根据我的需要进行调整,所以我写了这个在 VB.NET:
中开发的有用的代码片段''' ----------------------------------------------------------------------------------------------------
''' <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
加上另一个代码片段,以提供一种以编程方式安装产品密钥的方法(它在我的机器上使用 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
在同一个脚本中,您会找到 GetServiceObject
方法(以及它使用的常量和全局变量)。要找到它们,请在脚本中搜索以下术语:
- Function GetServiceObject
- ServiceClass =
- 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.");
}