SSIS脚本任务缺失DLL无法精准报错的原因及优化方案咨询
我们已经明确,在SSIS包的Script Task中使用第三方库时,需要手动将DLL添加至GAC(全局程序集缓存),并在Script Task的代码编辑器中添加该DLL的引用。但我们仍希望了解,未来若缺失其他DLL时,如何让SSIS Script Task给出精准报错提示。
测试场景构建方法
以AWSSDK.Core.dll为例,可通过以下两种方式触发缺失DLL错误:
- 进入目录
C:\Program Files (x86)\Microsoft SQL Server\130\DTS\Binn\,将AWSSDK.Core.dll重命名为AWSSDK.Core.dll.bak,使系统无法找到用于链接的DLL。 - 执行命令
gacutil -u AWSSDK.Core取消注册,此方法可在Visual Studio中触发测试错误,但在SQL Server部署环境中无效。
问题详情与临时解决方案
若Script Task使用如下源代码,其中RegionEndpoint region = RegionEndpoint.USEast1;依赖AWS库,缺失DLL时Visual Studio仅返回无明确指向的报错信息:
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
at Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTATaskScriptingEngine.ExecuteScript()
原代码:
public void Main() { try { RegionEndpoint region = RegionEndpoint.USEast1; bool fireAgain = false; Dts.Events.FireInformation(0, "Test", region.SystemName, string.Empty, 0, ref fireAgain); } catch (Exception ex) { Dts.Events.FireError(0, "Error", ex.Message, string.Empty, 0); throw; } Dts.TaskResult = (int)ScriptResults.Success; }
我们期望看到明确的缺失DLL异常,偶然间发现一种临时方案:1)将函数改为异步;2)将业务逻辑封装到另一个函数中在Main()内调用。修改后的代码如下:
#pragma warning disable CS1998 public async System.Threading.Tasks.Task Main() #pragma warning restore CS1998 { try { this.ScriptAction().GetAwaiter().GetResult(); } catch (Exception ex) { Dts.Events.FireError(0, "Error", ex.Message, string.Empty, 0); throw; } Dts.TaskResult = (int)ScriptResults.Success; } #pragma warning disable CS1998 async System.Threading.Tasks.Task ScriptAction() #pragma warning restore CS1998 { RegionEndpoint region = RegionEndpoint.USEast1; bool fireAgain = false; Dts.Events.FireInformation(0, "Test", region.SystemName, string.Empty, 0, ref fireAgain); }
疑问
- 我们仍不理解为何上述临时方案能返回精准的缺失DLL异常(如:
[File Not Found] Error: A required assembly is missing: AWSSDK.Core, Version=3.3.0.0, Culture=neutral, PublicKeyToken=885c28607f98e604),而直接使用void Main()却无法实现? - 可以看到我们需通过
#pragma warning disable CS1998抑制编译器警告,且SSIS Script Task对async/await支持不佳,同时我们的逻辑中并无实际异步操作,是否有更优方案? - SSIS Script Task除了缺失DLL外,是否还会遗漏其他异常?若会,该如何避免?
内容的提问来源于stack exchange,提问作者Mike

