PowerShell Core使用DacServices报EventDescriptor缺失错误解决
问题说明
在PowerShell Core 7.2.5脚本中使用DacServices时,触发类型依赖缺失报错:该类型依赖.NET 6未提供的System.Diagnostics.Eventing.EventDescriptor,先后测试SQL 15、SQL 16版本随安装包分发的DacServices,均无法正常运行。
原类型加载代码如下:
$sqlServerDacPaths = "${env:ProgramFiles}\Microsoft SQL Server\150\DAC\bin\Microsoft.SqlServer.Dac.dll", "${env:ProgramFiles}\Microsoft SQL Server\150\DAC\bin\Microsoft.SqlServer.Dac.Extensions.dll" foreach ($path in $sqlServerDacPaths) { if (Test-Path $path) { Write-Host "Adding $path" Add-Type -Path $path } } # 实例化DacServices $dacServices = New-Object Microsoft.SqlServer.Dac.DacServices $connectionString
实例化DacServices时抛出的异常信息:
“Microsoft.SqlServer.Dac.DacServices”的类型初始值设定项引发异常...
无法从程序集“System.Core, Version=4.0.0.0”中加载类型“System.Diagnostics.Eventing.EventDescriptor”
解决方法
报错核心原因是SQL Server安装目录下自带的Microsoft.SqlServer.Dac.dll是面向.NET Framework编译的版本,依赖很多.NET Framework独有的类型,无法在.NET 6(PowerShell 7的底层运行时)环境下直接加载。
最简便的修复方案是替换为官方提供的、适配.NET Core/.NET 6+的跨平台版本DacFx程序集,无需安装额外运行时或修改系统配置:
- 不要引用SQL Server安装目录下的Framework版本DacFx程序集
- 直接使用官方发布的适配.NET 6的DacFx包,可随脚本自动下载加载,无额外依赖
适配后可直接运行的代码如下:
# 配置参数,可按需升级DacFx版本号 $dacfxVersion = "162.1.160" $tempExtractPath = Join-Path $env:TEMP "dacfx_temp_$dacfxVersion" $nupkgSavePath = Join-Path $tempExtractPath "dacfx.nupkg" # 创建临时目录 New-Item -ItemType Directory -Path $tempExtractPath -Force | Out-Null # 下载对应版本的DacFx包 Invoke-WebRequest -Uri "https://www.nuget.org/api/v2/package/Microsoft.SqlServer.DacFx/$dacfxVersion" -OutFile $nupkgSavePath # 解压包(nupkg为标准zip格式) Expand-Archive -Path $nupkgSavePath -DestinationPath $tempExtractPath -Force # 加载.NET 6适配版本的DacFx程序集 $net6DacBinPath = Join-Path $tempExtractPath "lib/net6.0" Add-Type -Path (Join-Path $net6DacBinPath "Microsoft.SqlServer.Dac.dll") Add-Type -Path (Join-Path $net6DacBinPath "Microsoft.SqlServer.Dac.Extensions.dll") # 正常实例化DacServices,无依赖加载报错 $dacServices = New-Object Microsoft.SqlServer.Dac.DacServices $connectionString
补充说明:
- 160.0及以上版本的Microsoft.SqlServer.DacFx都提供net6.0适配构建,可以根据自己的需求替换更高的稳定版本号
- 如果不想每次跑脚本都重新下载包,可以提前把解压后
lib/net6.0目录下的所有dll放到脚本同级目录,直接加载本地路径即可,和原来的加载逻辑没有区别 - 该方案同时支持Windows、Linux、macOS下的PowerShell 7环境,没有平台限制
内容的提问来源于stack exchange,提问作者Brian Vallelunga
相关产品推荐
相关产品推荐

