我有一个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;
}
如何优雅地终止程序并打印警告信息? 如何在服务器上运行时显示此消息?
答案 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