2

我有一个以脚本任务开头的 SSIS 包,用于检查指定目录是否包含三个文件。如果有 2 个文件,它会打印一条警告,如果有 1 个或更少的文件,我想打印一条错误消息并终止程序。这个想法是 SQL 代理将注册我的包并在指定的时间执行它。但是,我的脚本中必须满足以下条件:

switch (numFiles)
            {
                case 0:
                    MessageBox.Show("Error: No files are in the directory C:\\Directory1\n Please restart execution.");
                    break;
                case 1:
                    MessageBox.Show("Error: Only one file was found in the directory C:\\Directory1\n Please restart execution.");
                    break;
                case 2:
                    MessageBox.Show("Warning: Only two files have been loaded into the directory C:\\Directory1\n Is this intended?.");
                    break;
            }

如何优雅地终止程序并打印警告消息?在服务器上运行时如何显示此消息?

4

2 回答 2

3

我认为最好通过挂钩现有的Events来为您服务。使用您的代码作为基线,我将一个变量添加到一个包中,然后部署到 SQL Server 中。

        int numFiles = Convert.ToInt32(Dts.Variables["numFiles"].Value.ToString());
        switch (numFiles)
        {
            case 0:
                //MessageBox.Show("Error: No files are in the directory C:\\Directory1\n Please restart execution.");
                Dts.Events.FireError(0, "File count", "Error: No files are in the directory C:\\Directory1\n Please restart execution.", string.Empty, 0);
                break;
            case 1:
                //MessageBox.Show("Error: Only one file was found in the directory C:\\Directory1\n Please restart execution.");
                Dts.Events.FireError(0, "File count", "Error: Only one file was found in the directory C:\\Directory1\n Please restart execution.", string.Empty, 0);
                break;
            case 2:
                //MessageBox.Show("Warning: Only two files have been loaded into the directory C:\\Directory1\n Is this intended?.");
                Dts.Events.FireWarning(0, "File count", "Warning: Only two files have been loaded into the directory C:\\Directory1\n Is this intended?.", string.Empty, 0);
                break;
        }

从命令行运行

"DTExec.exe" /file /set .\so_RaiseEvents.dtsx /set \Package.Variables[User::numFiles];0

"DTExec.exe" /file /set .\so_RaiseEvents.dtsx /set \Package.Variables[User::numFiles];1

"DTExec.exe" /file /set .\so_RaiseEvents.dtsx /set \Package.Variables[User::numFiles];2

我看到了预期的输出

Error: 2012-08-09 08:53:58.77
   Code: 0x00000000
   Source: Script Task File count
   Description: Error: No files are in the directory C:\Directory1
 Please restart execution.
End Error

Error: 2012-08-09 08:51:56.75
   Code: 0x00000000
   Source: Script Task File count
   Description: Error: Only one file was found in the directory C:\Directory1
 Please restart execution.
End Error

Warning: 2012-08-09 08:51:51.82
   Code: 0x00000000
   Source: Script Task File count
   Description: Warning: Only two files have been loaded into the directory C:\Directory1
 Is this intended?.
End Warning

当您从代理运行时应该显示警告,但如果没有,那么您需要在报告中添加一个参数,以便/report W

编辑

并解决这些问题

“我如何优雅地终止程序并打印警告消息” FireError 将导致 Script 任务返回失败代码Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,从而结束包执行。警告,如果您想停止包执行,那么您将修改脚本任务以指示它没有成功。我通过添加第三个 ScriptResult 枚举来做到这一点,该枚举被转换为DTSExecResult .Canceled (只有传达某些内容的其他选项没有按计划进行)。完整代码如下

[Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute]
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
{


    /// <summary>
    /// This method is called when this script task executes in the control flow.
    /// Before returning from this method, set the value of Dts.TaskResult to indicate success or failure.
    /// To open Help, press F1.
    /// </summary>
    public void Main()
    {
        int numFiles = Convert.ToInt32(Dts.Variables["numFiles"].Value.ToString());
        switch (numFiles)
        {
            case 0:
                //MessageBox.Show("Error: No files are in the directory C:\\Directory1\n Please restart execution.");
                Dts.Events.FireError(0, "File count", "Error: No files are in the directory C:\\Directory1\n Please restart execution.", string.Empty, 0);
                break;
            case 1:
                //MessageBox.Show("Error: Only one file was found in the directory C:\\Directory1\n Please restart execution.");
                Dts.Events.FireError(0, "File count", "Error: Only one file was found in the directory C:\\Directory1\n Please restart execution.", string.Empty, 0);
                break;
            case 2:
                //MessageBox.Show("Warning: Only two files have been loaded into the directory C:\\Directory1\n Is this intended?.");
                Dts.Events.FireWarning(0, "File count", "Warning: Only two files have been loaded into the directory C:\\Directory1\n Is this intended?.", string.Empty, 0);
                Dts.TaskResult = (int)ScriptResults.Warning;
                break;
            default:
                Dts.TaskResult = (int)ScriptResults.Success;
                break;
        }

    }

    /// <summary>
    /// This enum provides a convenient shorthand within the scope of this class for setting the
    /// result of the script.
    /// 
    /// This code was generated automatically.
    /// </summary>
    enum ScriptResults
    {
        Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
        Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure,
        Warning = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Canceled,
    };

}

似乎您希望有人在监视和响应包的运行。通常,这不是您希望 SSIS 做的事情。它可以做这些事情,你可以有一个消息框提示来发现用户是否希望继续,但是当它在服务器上运行时,包将无法通过验证检查,因为它会发现它没有在交互模式下运行。这比 DTS 好得多,因为人们会在服务器上留下消息框,并且由于没有人定期登录到服务器,包裹会挂起数周。如果您需要同时为两个主服务器(有人参与和无人参与的运行)提供服务,则使用 System::InteractiveMode 变量,这样您就不会尝试在无人参与的运行期间显示 UI 代码。

在我看来,一个更好的选择是保持 Event 的触发方式如上,以便它在自动化环境中运行良好。然后对于您的手动执行,提供一个轻量级的 .NET 包装器来运行作业。也将文件检查卸载到该位置。是的,工作是重复的,但您将更清晰地分离 ETL 和 UI 代码。

于 2012-08-09T13:57:13.553 回答
0

在服务器上运行时,您不能显示这样的消息框。

您应该写入日志文件 ( http://msdn.microsoft.com/en-us/library/ms167456%28v=sql.105%29.aspx )。

为了停止从脚本任务运行的包使用RunningPackage.Stop方法

        static void Main(string[] args)
        {
            Application app = new Application();
            RunningPackages pkgs = app.GetRunningPackages("yourserver");

            int pkgsRunning = pkgs.Count;
            Console.WriteLine("Packages before stop: thas + pkgsRunning);

            foreach (RunningPackage p in pkgs)
            {
                Console.WriteLine("InstanceID: " + p.InstanceID);
                Console.WriteLine("PackageDescription: " + p.PackageDescription);
                Console.WriteLine("PackageID: " + p.PackageID);
                Console.WriteLine("PackageName: " + p.PackageName);
                Console.WriteLine("UserName: " + p.UserName);
            }

            pkgs = app.GetRunningPackages("yourserver");
            foreach (RunningPackage package in pkgs)
            {
                package.Stop();
            }

            pkgsRunning = app.GetRunningPackages("yourserver").Count;
            Console.WriteLine("Packages after stop " + pkgsRunning);
        }

http://msdn.microsoft.com/en-us/library/microsoft.sqlserver.dts.runtime.runningpackage.stop.aspx

于 2012-08-09T12:27:33.787 回答