如何以及为什么使用regsvr32.exe工具[示例]

有时,如果你是Windows用户,很可能你曾经不得不运行regsvr32.exe 实用程序来“注册一个DLL”。如果是这样,你可能并不清楚在幕后到底发生了什么。这个神秘的实用程序用于管理许多Windows应用程序使用的对象链接和嵌入(OLE)控件

但究竟什么是OLE控件,为什么要注册OLE控件呢?在本教程中,你将学习使用regsvr32.exe 实用程序安装、卸载、注册或取消注册OLE控件的多种方法。

先决条件

确保你具备以下要求,以便跟着运行regsvr32.exe 实用程序:

  • 由于regsvr32.exe实用程序内置于大多数Windows版本中,你只需要一个带有管理员账户的Windows计算机。
  • 你将需要PowerShell 7来利用本教程中包含的PowerShell脚本。

什么是OLE控件?

在学习如何使用regsvr32.exe 实用程序之前,你必须首先对这个工具管理的OLE控件有一个基本的了解。

OLE控件是一种专门针对Windows开发的技术,用于方便地嵌入和链接文档和其他对象。这项技术经过多年发展,不同的组件都是在OLE技术的基础上构建而成的。

你可能听说过组件对象模型(COM)、分布式组件对象模型(DCOM)或者ActiveX控件。这些技术中的每一种都是建立在OLE技术之上或者是其扩展,定义了一个标准接口,用于在许多不同的编程语言中编写功能。

ActiveX已经被弃用,但仍然可以通过Internet Explorer在Windows 10上使用,但不能在Microsoft Edge上使用。

注册OLE控件

现在您了解了regsvr32.exe实用程序的作用,是时候注册一个OLE控件了,有几种命令变体可以完成这项任务。随意选择以下其中一种命令变体,或者尝试每一种。

您可以通过PowerShell或Windows命令提示符注册OLE控件。无论哪种方式,确保您以管理员身份运行命令行以确保控件被正确注册。

显示GUI结果

注册一个DLL使用regsvr32,在最简单的用例中,涉及将DLL路径传递给该工具。默认情况下,regsvr32将显示一个弹出窗口,指示成功(或失败)。要注册一个DLL,请提供DLL的名称或完整路径,如下所示。

运行下面的命令将为目标OLE控件在HKEY_CLASSES_ROOT\CLSID键的x64实例或HKEY_CLASSES_ROOT\WOW6432Node\CLSID键的x86实例中创建必要的注册表类。

regsvr32 msxml3.dll

成功后,您将看到一个GUI结果,指示DllRegisterServer成功。

Registering a DLL

注册OLE控件时,regsvr32.exe将应用系统搜索路径。因此,如果您需要在该路径之外注册特定文件,最好指定文件的绝对路径。

悄悄注册OLE控件

在运行命令时,不总是希望显示GUI提示。因此,让我们了解如何在注册OLE控件时抑制任何GUI提示。

要抑制GUI提示,运行regsvr32,后面跟着DLL名称(msxml3.dll)和/s开关以悄悄注册OLE控件。这个命令的唯一缺点是您还将抑制任何错误消息。

还有一个未记录的开关/e存在,仅抑制GUI成功消息但显示GUI错误消息——聪明!

regsvr32 msxml3.dll /s
Registering a DLL silently

注册OLE控件并指定安装操作

当您为OLE注册指定DLL时,您仅调用DllRegisterServer方法,但有时您需要在注册后执行操作。为此,您可以指定/i参数。

例如,您可以将输入字符串(U)传递给/i参数,这将同时调用DllInstall方法和DllRegisterServer方法。

DllInstall方法允许regsvr32.exe实用程序以多种方式安装DLL,并为一个DLL调用各种操作。

regsvr32 /i:U shell32.dll
Registering a DLL and running an install command

指定不调用DllRegisterServer方法的安装操作

也许您只想安装一个OLE控件而不重新注册它。如果是这样,请运行以下命令。

regsvr32 /n /i:U shell32.dll

上面的命令使用/n参数防止为shell32.dll DLL调用DllRegisterServer方法,而是调用安装方法DllInstall。

Only running an install command but not registering a DLL

使用regsvr32.exe取消注册OLE控件

如果您已经成功注册了OLE控件,那真是个安慰。但可能会有一些时候,当它与其他控件冲突时,您需要卸载OLE控件。幸运的是,regsvr32.exe提供了取消注册和卸载OLE控件的功能。

要取消注册并卸载控件,请运行regsvr32.exe并传递/u参数来取消注册OLE控件。您可以在下面的GUI结果中看到msxml3.dll DLL已成功卸载。

要在取消注册的同时运行操作,请将操作字符串(U)传递给/i参数。然后,regsvr32命令将以该操作作为卸载的DllInstall方法调用,如下所示:regsvr32 /i:action /U msxml3.dll

regsvr32 /U msxml3.dll
Unregistering a DLL

处理regsvr32.exe的错误

您已成功注册OLE控件,但如果注册命令遇到错误怎么办?在尝试管理控件时可能会出现一些错误。这些消息有时可能会很难理解,但下面将对其进行解释,以便让您了解其原因。

FAIL_ARGS ⦿ “Unrecognized flag”
⦿ “Extra argument on command line”
⦿ “This command is only valid when an OLE Custom Control project is open”
⦿ “No DLL name specified”
Implies that a command-line argument was incorrect.
FAIL_OLE “OleInitialize failed” Implies that there was an error in properly initializing the OLE subsystem.
FAIL_LOAD LoadLibary(<dllname) failed> This can be a host of reasons such as a dependent library missing, the DLL is inaccessible due to permissions, or the file is missing.
FAIL_ENTRY ⦿ ” was loaded, but the entry point was not found. does not appear to be an .DLL or .OCX file”
⦿ ” was loaded, but the entry point was not found. may not be exported or a corrupt version may be in memory. Consider using PView to detect and remove it.”
⦿ ” was loaded, but the entry point was not found. may not be exported, or a corrupt version may be in memory. Consider using WPS to detect and remove it.”
Implies that the entry point in the DLL, or function name, is missing.
FAIL_REG <DLLEntryPoint> in <DLLName> failed Implies that despite all the prior steps completing the system still failed to fully register the DLL.

使用PowerShell扩展regsvr32.exe实用程序

regsvr32.exe更喜欢GUI输出,自动化可能会有挑战。为了摆脱这种挑战,您可以将regsvr32.exe实用程序包装在PowerShell函数中。通过创建PowerShell函数,您可以像运行本机PowerShell cmdlet一样运行regsvr32.exe

作为示例,查看下面的Invoke-RegSvr32 PowerShell函数。此函数调用regsvr32实用程序,并使用PowerShell捕获退出代码并相应地处理它。而且,通过提前应用参数验证,甚至可以完全避免错误!

要尝试下面的函数,请打开一个新的PowerShell控制台,并将代码复制粘贴到其中。然后,您就可以像下面显示的那样调用该函数。

Function Invoke-RegSvr32 {
	<#
	.SYNOPSIS
	包装regsvr32.exe Windows实用程序以注册OLE控件的PowerShell函数,以帮助自动化。
	
	.PARAMETER FilePath
	指定要传递给regsvr32.exe的DLL或控件名称,必须是有效的文件路径。
	
	.PARAMETER InstallString
	指定一个字符串值作为注册控件时DllInstall函数中的pszCmdLine值传递。
	
	.PARAMETER Unregister
	注销先前注册的控件。
	
	.PARAMETER InstallOnly
	不注册控件,仅运行DllInstall函数,还必须传递一个InstallString。
	
	.EXAMPLE
	PS> Invoke-RegSvr32 "C:\\Windows\\System32\\msxml3.dll"
	#>
  [CmdletBinding()]
  
  Param (
    [ValidateScript({ Test-Path -Path $_ -PathType 'Leaf' })]
    [String]$FilePath,
    [ValidateScript({-Not [String]::IsNullOrWhiteSpace($_)})]
    $InstallString,
    [Switch]$Unregister,
    [Switch]$InstallOnly
  )

  Begin {
    # 错误代码在这篇微软文章中有文档记录
	  # <https://devblogs.microsoft.com/oldnewthing/20180920-00/?p=99785>
    $ExitCodes = @{
      0 = "SUCCESS";
      1 = "FAIL_ARGS - Invalid Argument";
      2 = "FAIL_OLE - OleInitialize Failed";
      3 = "FAIL_LOAD - LoadLibrary Failed";
      4 = "FAIL_ENTRY - GetProcAddress failed";
      5 = "FAIL_REG - DllRegisterServer or DllUnregisterServer failed.";
    }
  }

  Process {
    If ($InstallOnly -And -Not $InstallString) {
      Write-Error "If you are running DllInstall by itself, an install string must be included."
      Return
    }

    $Arguments = "/s{0}{1}{2} {3}" -f
      (($Unregister) ? ' /U': ''),
      (($InstallString) ? " /i:$InstallString": ''),
      (($InstallOnly) ? ' /n': ''),
      $FilePath

    Write-Verbose $Arguments

    Try {
      $Result = Start-Process -FilePath 'regsvr32.exe' -Args $Arguments -Wait -NoNewWindow -PassThru

      If ($Result.ExitCode -NE 0) {
        Write-Error $ExitCodes[$Result.ExitCode]
      }
    } Catch {
      Write-Error $_.Exception.Message
    }
	}
}

以下是如何使用 Invoke-RegSvr32 函数的几个示例。

 # 尝试只针对 msxml3.dll 运行 DllInstall 并输出详细信息
 Invoke-RegSvr32 "C:\Windows\System32\msxml3.dll" -Verbose -InstallOnly
 
 # 尝试以静默方式注册 msxml3.dll 并输出详细信息
 Invoke-RegSvr32 "C:\Windows\System32\msxml3.dll" -Verbose
 
 # 尝试以静默方式注册 msxml3.dll 但不输出信息
 Invoke-RegSvr32 "C:\Windows\System32\msxml3.dll"
Running Invoke-RegSvr32 PowerShell Command

结论

到目前为止,您已经学会了如何注册和注销 DLL 以及处理错误。虽然 regsrv32.exe 在日常任务中可能用得不那么频繁,但在某些情况下,您可能需要注册或注销 DLL。

为了进一步扩展功能,您甚至可以扩展 PowerShell 来处理更多的检查和边缘情况。您甚至可以创建一个 PowerShell 函数来列出在 CLSID 注册表位置中注册的控件!

Source:
https://adamtheautomator.com/regsvr32-exe/