SSIS C#Script自动化任务

时间:2012-08-09 12:09:21

标签: c# ssis automation task

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

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;
            }

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

2 个答案:

答案 0 :(得分: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将导致脚本任务返回失败代码Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,从而结束程序包执行。警告,如果你想要停止包执行,那么你将修改脚本任务,以表明它没有成功。我这样做是通过添加第三个ScriptResult枚举的Warning,它被转换为DTSExecResult。取消(只有其他选项传达的东西没有计划)。完整代码在

之下
[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代码。

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

答案 1 :(得分: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