Powershell 注册.dll类库到系统

张开发
2026/4/20 10:09:11 15 分钟阅读

分享文章

Powershell 注册.dll类库到系统
目录一. 简介二. 程序代码2.1 管理员权限执行脚本2.2 自定义函数2.3 注册代码三. 注册成功一. 简介在C# 创建vba用的类库的文章中介绍了创建vba类库的方式。但是vba无法直接使用.dll文件必须将.dll文件注册到系统中然后vba才能调用。vba依赖于Excel而Excel又有32位和64位这两种版本32位Excel使用$env:WINDIR\Microsoft.NET\Framework\v4.0.*\RegAsm.exe注册64位Excel使用$env:WINDIR\Microsoft.NET\Framework64\v4.0.*\RegAsm.exe注册RegAsm.exe是系统自带的一般在上面的路径中都会存在为了脚本的通用性在注册的时候会同时注册32位和64位。保证所有位数的Excel都可以使用。当使用RegAsm.exe将.dll类库注册成功之后会将.dll类库的相关信息写入注册表效果如下图所示$ProgId ToolLib.ToolComC# 创建vba用的类库文章中提到的ProgId{6143FB0B-9C17-4859-860C-6DA4A466ECD1}.dll类库关联的Guid二. 程序代码2.1 管理员权限执行脚本使用RegAsm.exe时必须通过管理员权限因此在脚本中加入管理员权限判断。若不是管理员则转换为管理员权限后再执行脚本。param([string]$originalScriptFolderPath)# 校验当前用户是否有管理员权限functionTest-IsAdmin{$id[System.Security.Principal.WindowsIdentity]::GetCurrent()$principalNew-ObjectSystem.Security.Principal.WindowsPrincipal($id)if($principal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)){return$true}return$false}# 若没有管理员权限if(-not(Test-IsAdmin)){Write-Host未检测到管理员权限正在尝试重新启动为管理员模式...-ForegroundColor Yellow# 暂停1秒钟, 显示文字Start-Sleep-Seconds 1# 以管理员方式启动当前脚本Start-Process-FilePathpowershell.exe-ArgumentList-NoProfile -ExecutionPolicy RemoteSigned -File$($PSCommandPath)-originalScriptFolderPath$($PSScriptRoot)-Verb RunAs# 退出当前脚本, 防止打开多个窗口exit}Write-Host已成功以管理员权限运行PowerShell ...n-ForegroundColor Green# 当以管理员权限运行脚本的时候, 作业目录默认会移动到【C:\WINDOWS\system32】下# 我们手动将作业目录其移动到脚本所在的文件夹路径if($null-ne$originalScriptFolderPath){Set-Location$originalScriptFolderPath}2.2 自定义函数注册Com所需的参数/codebase告诉COMDLL文件所在的绝对路径会在注册表的指定项的InprocServer32中写入.dll文件的绝对路径/tlb给COM客户端尤其 VBA用的接口描述文件里面描述了接口, 方法, 参数类型非必须参数但是添加了这个参数之后, vba可以在【工具】→【引用】中找到自定义的.dll然后就可以进行早绑定了functionRegister-Com{param([string]$dllFullPath,[string]$regAsmExeFullPath)$versionMsg32位if($regAsmExeFullPath.Contains(Framework64)){$versionMsg64位}$params$dllFullPath /codebase /tlb$result$nulltry{$resultStart-Process$regAsmExeFullPath-ArgumentList$params-Wait-PassThruif($result.ExitCode-eq0){Write-Host${versionMsg}的dll注册成功}}catch{Write-Host${versionMsg}的dll注册失败:$($result.ExitCode)Write-Host${versionMsg}的dll注册失败:$($_.Exception.Message)}}# 卸载ComfunctionUnregister-Com{param([string]$dllFullPath,[string]$regAsmExeFullPath)$versionMsg32位if($regAsmExeFullPath.Contains(Framework64)){$versionMsg64位}# 卸载Com所需的参数$params$dllFullPath /unregister$result$nulltry{$resultStart-Process$regAsmExeFullPath-ArgumentList$params-Wait-PassThruif($result.ExitCode-eq0){Write-Host${versionMsg}的dll卸载成功}}catch{Write-Host${versionMsg}的dll卸载失败:$($result.ExitCode)Write-Host${versionMsg}的dll卸载失败:$($_.Exception.Message)}}32位的PowerShell, 只能验证32位的com现在大多数电脑都是64位的因此使用32位的PowerShell时必须指定路径functionTest-32ComBoth{param([string]$progId)# 32位Powershell的路径$powershell32$env:WINDIR\SysWOW64\WindowsPowerShell\v1.0\powershell.exe$script try { New-Object -ComObject $progId | Out-Null Write-Host ${progId}的32位COM存在 } catch { Write-Host ${progId}的32位COM不存在 } # 测试32位com$powershell32-NoProfile-Command$script}64位的PowerShell, 只能验证64位的com现在大多数电脑都是64位的默认的PowerShell也都是64位的所以不需要指定PowerShell路径functionTest-64ComBoth{param([string]$progId)# 测试64位comtry{New-Object-ComObject$progId|Out-NullWrite-Host${progId}的64位COM存在}catch{Write-Host${progId}的64位COM不存在}}2.3 注册代码# 要安装的.dll库的路径, 此处设定为和脚本同一级别的目录下[string]$dllPath.\03-ToolLib.dll# .dll库的ProgId$ProgIdToolLib.ToolCom# 获取32位和64位的RegAsm.exe的路径, 由于不知道具体版本, 所以使用了通配符$regAsm32ExePath$env:WINDIR\Microsoft.NET\Framework\v4.0.*\RegAsm.exe$regAsm64ExePath$env:WINDIR\Microsoft.NET\Framework64\v4.0.*\RegAsm.exe# 获取RegAsm.exe的绝对路径$regAsm32ExeFullPath(Get-ChildItem$regAsm32ExePath-ErrorAction SilentlyContinue|Select-Object-First 1).FullName$regAsm64ExeFullPath(Get-ChildItem$regAsm64ExePath-ErrorAction SilentlyContinue|Select-Object-First 1).FullName# 如果32位和64位的RegAsm.exe有任意一个不存在的话if((-not$regAsm32ExeFullPath)-or(-not$regAsm64ExeFullPath)){Write-Host找不到RegAsm.exe文件...Pauseexit1}# 通过相对路径获取绝对路径$fullPathObjResolve-Path$dllPath-ErrorAction SilentlyContinueif(-not$fullPathObj){Write-Host找不到${dllPath}文件...Pauseexit1}# 获取dll文件的绝对路径$dllFullPath$fullPathObj.Path# 让用户选择要执行的操作[string]$confirmRead-Host选择要执行的操作. 1. 安装依赖库 2. 卸载依赖库if($confirm-eq2){# 卸载32位的comUnregister-Com-dllFullPath$dllFullPath-regAsmExeFullPath$regAsm32ExePath# 卸载64位的comUnregister-Com-dllFullPath$dllFullPath-regAsmExeFullPath$regAsm64ExePathPauseexit}elseif($confirm-ne1){Write-Host请输入 1 或者 2Pauseexit}# 注册32位的comRegister-Com-dllFullPath$dllFullPath-regAsmExeFullPath$regAsm32ExePath# 注册64位的comRegister-Com-dllFullPath$dllFullPath-regAsmExeFullPath$regAsm64ExePath# .dll类库中的命名空间和方法名Test-32ComBoth$ProgIdTest-64ComBoth$ProgId# 根据 ProgId 查询注册表路径是否存在$RegistryProgIdPathRegistry::HKEY_CLASSES_ROOT\$ProgId\if(-not(Test-Path$RegistryProgIdPath)){Write-Host找不到${RegistryProgIdPath}注册表...Pauseexit1}# 获取 .dll库的Guid# {6143FB0B-9C17-4859-860C-6DA4A466ECD1}$dllCLSID(Get-Item$RegistryProgIdPath\CLSID).GetValue()# 查询32位.dll对应的注册表Get-ChildItemRegistry::HKLM\Software\Classes\WOW6432Node\CLSID\$dllCLSID-ErrorAction SilentlyContinue# 查询64位.dll对应的注册表Get-ChildItemRegistry::HKEY_CLASSES_ROOT\CLSID\$dllCLSID-ErrorAction SilentlyContinue Pause三. 注册成功

更多文章