【问题标题】:Script task knows there is a variable but crashes if I attempt to use it脚本任务知道有一个变量,但如果我尝试使用它就会崩溃
【发布时间】:2021-05-23 14:17:46
【问题描述】:

setting up the container Assigning the script variables

好的,所以无论我如何处理变量,我的脚本任务都无法使用它们。抛出的错误是通用的,但由于我正在使用 SSDT,我无法单步执行代码或进行任何合理的调试。

我已将其剥离到卸载并重新安装 SSDT 的位置,并从头开始使用一个新包,一次将一行代码添加到自动生成的 ScriptTask 代码中,以确保我是没有遗漏任何东西。一切运行正常,直到我尝试使用包变量提取任何东西,我从自动帮助中复制的代码,并针对 SO 和其他来源进行了验证。 "dts.Variables("User::variablename").value.toString()" 应该根据一切工作,但我无处可去。

我已经尝试过“User::FromFile”、“FromFile”、“Package::FromFile”、“Project::FromFile”和“variables.item(1)”,但这些变体都不起作用.

dts.variables.count 表明脚本确实知道那里有一个变量,并且该变量确实填充,因为我可以获得后续数据流任务来尝试基于它打开文件。

Public Sub Main()
'
' Add your code here
'
Dim currFileName As String
Dim n As Integer
Dts.Events.FireInformation(0, "Script Task", "variables count: " & CType(Dts.Variables.Count, String), "", 0, True)
For n = 1 To Dts.Variables.Count
    Dts.Events.FireInformation(0, "Script Task", CType(Dts.Variables.Item(n).Name.ToString, String) & " : " & CType(Dts.Variables.Item(n).Value, String), "", 0, True)
Next

' Debugging - assiging a file path explicity here does work so the loop and the code is fine
Dim filePath As String = "\\Path\File.csv"

Dts.Events.FireInformation(0, "Script Task", "Reading in file " & filePath, "", 0, True)
Try
    currFileName = CType(Dts.Variables("FromFile").Value.ToString, String)
Catch
    Dts.Events.FireError(999, "Reading Variable", "Can't read filename from variable name", "", 0)
End Try
Dts.Events.FireInformation(0, "Script Task", "Reading in file " & FilePath, "", 0, True)
Dim lines() As String = System.IO.File.ReadAllLines(filePath)
Dts.TaskResult = ScriptResults.Success
End Sub

编辑:使用下面的代码从头开始工作。 但是我仍然不清楚为什么以前尝试使用“.ToString()”或“CType(Dts.Variables(”name任何变化“)。值,字符串)”都不起作用。

即使我将所有这些尝试都包含在 Try-Catch 循环中,我仍然一无所获,我原以为 VB 至少会发现错误,但什么也没有。

更新 #2 目前在......“在 try/catch 中添加一行/代码块并处理错误”的迭代 40(?)。我仍然不明白为什么 try/catch 不能阻止这些调用错误。确定这就是重点吗?

更新 #3 添加额外的 FireInformation 事件会导致失败。将它们注释掉并没有改变失败。重新启动 VS,脚本在几秒钟内完成……什么也没做。注释掉除了@billinkc 的有效代码之外的所有内容......仍然什么都不做。失去住在这里的意愿。

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()

【问题讨论】:

    标签: ssis sql-server-data-tools


    【解决方案1】:

    我相信您的根本问题是您将函数 ToString 用作指针而不是调用它。即 Value.ToString 而不是 Value.ToString() 我的 VB 生锈了,所以我可以离开。一起来探索

    我创建了一个 SSIS 变量、一个包参数和一个项目参数,它们都称为 FromFile 并用字符串初始化它们以验证我看到的是预期值。

    我添加了一个脚本任务,将语言设置为 VB 并将上述变量添加到我的 ReadOnlyVariables 集合User::FromFile,$Package::FromFile,$Project::FromFile

    我在我的 SSIS 包中充分利用了以下脚本。它枚举它可以访问的任何变量,并将结果推送到 OnInformation 事件流。在 Visual Studio 中,这将显示在“执行结果”面板“输出”选项卡中 - 这更有用。在 SSISDB 中运行时,除非您关闭了信息事件,否则您会看到它记录在 SSISDB.catalog.operation_messages

    Public Sub Main()
        Dim fireAgain As Boolean = False
        For Each item As Variable In Dts.Variables
            Dim template As String = "{0}::{1}->{2}"
            Dim message As String = ""
            message = String.Format(template, item.Namespace, item.Name, item.Value)
            Dts.Events.FireInformation(0, "Scr Echo", message, "", 0, fireAgain)
        Next
        Dts.TaskResult = ScriptResults.Success
    End Sub
    

    在“输出”选项卡中,这是我看到的

    Information: 0x0 at SCR Echo Back, Scr Echo: $Package::FromFile->I am package parameter
    Information: 0x0 at SCR Echo Back, Scr Echo: $Project::FromFile->I am project parameter
    Information: 0x0 at SCR Echo Back, Scr Echo: User::FromFile->Hello world from Variable
    

    作为额外的好处,我们看到参数、Package:: 和 Project:: 将不起作用,因为现在这些参数是这样处理的。应该是$Package::FromFile$Project::FromFile

    现在我知道我能够正确访问变量或参数的值,让我们深入研究一下我是否可以重现您的错误或提供工作代码。我对您的代码期望的内容还不够了解。你有两个变量,filePathcurrFileName. filePath 被初始化为一个完全限定的路径,也许吧?您要么使用 UNC 但未指定共享,要么使用本地路径,在该路径中您已对斜线进行了半双转义。我们为 currFileName 分配一个值,该值来自我们的变量。

    但是,我们使用 filePath 变量作为 ReadAllLines 的源。

    Public Sub Main()
        Dim filePath As String = "C:\ssisdata\Input\SO_67660730.DoesNotExist.txt"
        Dim fireAgain As Boolean = False
        Dim lines() As String
        If (False) Then
            For Each item As Variable In Dts.Variables
                Dim template As String = "{0}::{1}->{2}"
                Dim message As String = ""
                message = String.Format(template, item.Namespace, item.Name, item.Value)
                Dts.Events.FireInformation(0, "Scr Echo", message, "", 0, fireAgain)
            Next
        End If
    
        ' Populate our filePath local variable with the value from the Variable collection
        ' Option A Blindly assume the first element in our collection is what we want
        filePath = Dts.Variables(0).Value.ToString()
        Dts.Events.FireInformation(0, "Option A", filePath, "", 0, fireAgain)
    
        ' Fully qualified named value
        filePath = Dts.Variables("User::FromFile").Value.ToString()
        Dts.Events.FireInformation(0, "Option B", filePath, "", 0, fireAgain)
    
        ' Either way, we have the file path available to us, let's read the data
        If (System.IO.File.Exists(filePath)) Then
            lines = System.IO.File.ReadAllLines(filePath)
            Dts.Events.FireInformation(0, "Rows Read", lines.Length.ToString(), "", 0, fireAgain)
        Else
            Dts.Events.FireInformation(0, "No file found", filePath, "", 0, fireAgain)
        End If
    
        Dts.TaskResult = ScriptResults.Success
    End Sub
    

    结果是

    Information: 0x0 at SCR Read File, Option A: C:\ssisdata\Input\SO_67660730.txt
    Information: 0x0 at SCR Read File, Option B: C:\ssisdata\Input\SO_67660730.txt
    Information: 0x0 at SCR Read File, Rows Read: 3
    

    如果您坚持使用 VB.NET 作为您的语言,您将需要查找基于 2005/2008 版 SSIS 构建的博客和示例,因为这是我们唯一可用的语言。世界上大多数国家都采用 C# 作为 SSIS 脚本和任务的主要语言,但 Solisyon 的 Ben Weissman 在他的示例中使用 VB。

    【讨论】:

    • 好的,谢谢,这是很好的指导。我曾尝试过这样的循环“For n = 1 To Dts.Variables.Count”,但它不起作用 - 将 n 更改为 0 似乎已经解决了这个问题。我还尝试了“Value.ToString”、“Value.ToString()”和“Ctype(..Value,String)”的变体,所有这些似乎都不起作用。仍在努力。为每个部分添加更多尝试...捕获。
    • 好吧,代码已经继续,但是我仍然收到相同的一致通用错误:“错误:调用目标已引发异常。”但是构建日志显示没有错误,我已经输入并转换了所有变量。令我沮丧的是,我的工作代码具有固定路径,当我将其移动到 For 循环并使用变量时,会触发此“错误:调用目标已引发异常”。一般错误。我无法深究。
    • 这是 SSIS 错误,而不是 .net 错误。设置一个断点,你会得到一个更好的错误,
    • 感谢@billinkc 繁琐的工作,我正在度过难关。但是我很感兴趣你知道更多关于“.ToString()”的信息。当我使用“x = y.ToString”时,它不起作用,我必须使用“x = y.ToString()”。然而,当我放入 Events.FireInformation 块来调试变量中的内容时,'Thing : " & x.ToString & "." ' 有效,而 ' Thing : " & x.ToString() & "." ' 没有。这对我来说毫无意义……或者我是在产生幻觉。在这两种情况下,我都希望有一种方法来进行字符串转换并返回一个字符串。两者都是相同的通用错误....
    • 谢谢@KeithL。不幸的是,SSDT 不允许我设置断点(或者更确切地说不会支持它们),而且我还没有在这台机器上激活 VS 许可证。
    猜你喜欢
    • 2021-08-22
    • 1970-01-01
    • 2016-12-13
    • 2013-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多