【问题标题】:SSIS Script Task reference dll programmaticallySSIS Script Task 以编程方式引用 dll
【发布时间】:2020-11-09 14:15:15
【问题描述】:

我已经构建了能够自动导出 DTSX 包的软件。这个包在其他对象中也有一个 ScriptTask (C#)。全部编译并运行良好。

现在的新要求是调用该 ScriptTask 中的一个类,该类存在于我们构建的外部 DLL 中,因此其他应用程序可以使用相同的代码。我们做了功课,在安装软件的过程中,我们成功地将这个 DLL 包含到了 GAC 中。

问题是脚本中仍然无法识别“使用我们的库”。

经过一番搜索,我们发现,我们还需要在 References 文件夹中引用这个 DLL。我们当然可以通过 DataTools / VisualStudio UI 来做到这一点。

问题是我们需要以编程方式进行:

我们有这段代码可以生成项目

task.ScriptingEngine.VstaHelper.LoadNewProject(task.ProjectTemplatePath, null, "MyScriptProject");

而且,我们有这段代码可以创建 MainScript

task.ScriptingEngine.VstaHelper.AddFileToProject(ScriptName + ".cs", MainScript.ToString());

我无法弄清楚如何以编程方式包含参考 DLL。

【问题讨论】:

    标签: dll ssis external gac programmatically


    【解决方案1】:

    更新答案

    您可以通过替换 DTSX 文件中的相应 XML 节点以编程方式更新脚本任务

    节点路径取决于在 SSIS 包中创建脚本任务的位置,在我的例子中节点路径是

    /DTS:Executable/DTS:Executables/DTS:Executable/DTS:ObjectData/pipeline/components/component[@refId="Package\Data Flow Task\Script Component"]/properties

    您要查找的@refId 将以包\数据流名称\组件名称开头

    此节点将具有包含 C# 脚本以及基于此脚本构建的二进制文件的子节点

    属性名称“SourceCode”包含一个名为arrayElements的数组中的C# scipts,该数组将为每个文件有三个子节点,这些子节点称为arrayElement,第一个值是相对路径和名称,第二个是文件编码和三是文件内容

    属性名称“BinaryCode”包含从脚本构建的 .dll,它还包含一个带有两个条目的 arrayElement 数组,第一个是 dll 名称,第二个是 base64 编码的 dll 二进制文件

    要获取数据以填充这些项目,您需要创建 C# 构建目录的模板、应用更改、构建代码并获取生成的文件并在相应的节点上替换它们

    要创建模板,请通过 SSIS 任务打开脚本,

    1. 在解决方案资源管理器中单击项目并转到文件保存 VstaProject.sln
    2. 转到保存的文件夹,您从解决方案属性对话框中获取该文件夹
    3. 将此文件夹复制到某处,以便您可以重复使用它来构建您的自定义内容
    4. 修改模板目录中的 .cs 文件并将自定义引用 dll 添加到 .csproj 文件中
    5. 调用与你的.csproj同目录的MSBUILD输出dll,重要的是你使用VS MSBUILD,VS2017你可以在

    C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\msbuild.exe

    1. 获取这些文件并将它们打包到 DTSX 文件中的 XML 节点中

    初步回答

    Microsoft 为加载不在 GAC 中的 DLL 提供了一种解决方法

    Load assembly that isnt in the GAC

    请参阅下面的 SSIS 脚本摘录,我从 nuget 安装目录加载了 JSON dll。此 DLL 不在 GAC 中

    static ScriptMain()
    {
        AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
    }
    static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        if (args.Name.Contains("Newtonsoft.Json"))
        {
            string path = @"C:\Program Files\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\plugins\Diagnostics\";
            return System.Reflection.Assembly.LoadFile(System.IO.Path.Combine(path, "Newtonsoft.Json.dll"));
        }
        return null;
    }
    

    【讨论】:

    • 嗨@Ockert Pretorius,我知道您正在使用此代码加载不在GAC 中的DLL,但您仍然应该在引用中引用该DLL,对吗?
    • @StavrosKoureas ,是的,我错过了您问题的那一部分,您仍然需要从脚本任务中创建对它的引用,因为脚本任务会编译二进制文件并将其保存在 dtsx 中。您可以在 ssis 之外编译并将结果存储在 dtsx 中,或者如果二进制文件没有更改,您可以编译它并重用它。脚本代码和二进制文件作为 CDATA 以 XML 格式存储在 dtsx 文件中
    • 是的,这是关键问题,所以,您知道我们如何以编程方式添加引用吗?或者您能否提供有关我们如何以编程方式将编译后的库作为 CDATA 添加到 DTSX 定义中的任何信息? (我们使用 EzAPI 和标准 Microsoft DTS 库构建了包)
    • 脚本任务有变化吗?如果输入和输出保持不变,您可以将 CDATA 移植到新的 DTSX 中。如果输入和输出发生变化,您需要重新编译和替换二进制数据,这应该是可能的,但在技术上会很困难
    • @StavrosKoureas 我已经更新了我的答案,我将如何构建一个包含引用的自定义脚本任务 dll
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多