我该如何执行此文件/文件夹分发任务; SSIS或命令脚本?

时间:2013-02-19 15:24:51

标签: batch-file ssis

我需要执行以下概述的任务,并且不确定如何继续。使用Windows Server 2003,我可以在命令脚本中执行此操作,还是在SSIS中执行脚本任务?我一直在使用SSIS 2005并知道有一个文件系统任务,但我以前从未使用它。

  • 我在本地有一个'target.file'文件。
  • 网络服务器上有一个“目标”文件夹。
  • 'target'下有几百个文件夹。
  • 其中一些文件夹下有'备份'文件夹。
  • 我需要将'target.file'复制到'target'文件夹下的那些文件夹中。
    • 但是如果已经存在'target.file',则只复制/替换。
    • 如果存在'target.file',则在备份文件夹存在的情况下将文件复制并替换到备份文件夹。
    • 如果没有,请先创建备份文件夹。

2 个答案:

答案 0 :(得分:4)

使用C#和VB.NET

在SSIS 2012中编写的示例包

以下是在SSIS 2012中编写的示例包,它使用脚本任务执行您要查找的内容。您不需要使用SSIS。您甚至可以使用简单的C#或VB.NET控制台应用程序执行此操作,但SSIS可以灵活地记录信息并安排作业。

文件夹结构(初始)

我们假设文件夹的结构如下所示:

您要复制一个源文件。

Source
    |- Sample_File.txt

这是目标文件夹结构。

Target
    |- Target_1
    |    |- Archive
    |    |- Sample_File.txt
    |- Target_2
    |- Target_3
        |- Sample_File.txt

创建SSIS包并创建文件夹变量:

Variable name       Data type  Value
------------------ ---------- ----------------------
Backup_FolderName  String      Archive
Source_FileName    String      Sample_File.txt
Source_FilePath    String
Source_Folder      String      D:\SSIS\Files\Source\
Target_Folder      String      D:\SSIS\Files\Target\

选择变量 Source_FilePath ,然后点击 F4 查看属性。将属性 EvaluateAsExpression 更改为true。单击 Expression 属性旁边的省略号按钮以打开 Expression Builder 。将表达式设置为@[User::Source_Folder] + "\\" + @[User::Source_FileName]

您可以只使用一个变量来存储源文件路径。我通常更喜欢将源文件夹和文件名分开。

将脚本任务拖放到控制流选项卡上。双击脚本任务以打开脚本任务编辑器。在脚本选项卡页面上,单击ReadOnlyVariables旁边的省略号按钮并选择以下变量,因为我们将在脚本任务代码中使用这些变量。

User::Source_FilePath
User::Target_Folder
User::Backup_FolderName

单击编辑脚本... 按钮并输入如下所示的代码。

C#中的脚本任务代码仅适用于SSIS 2008及以上版本:

脚本任务代码执行以下操作:

  • 它将检查源文件路径是否有效。如果无效,它将抛出一条消息并退出该过程。

  • 它将检查目标文件夹是否有效。如果无效,它将抛出一条消息并退出该过程。

  • 如果源文件路径和目标文件夹有效,则逻辑将遍历目标文件夹内子文件夹中源文件名的所有匹配位置。如果有匹配的文件,它会将目标文件复制到备份文件夹,然后用源文件覆盖目标文件。

  • 脚本任务将发出相应的信息,以便您可以在SSIS 2012中的SQL Server数据工具(SSDT)或SSIS 2005中的Business Intelligence Development Studio(BIDS)中跟踪进度/执行结果选项卡中的状态 - SSIS 2008 R2。

    区域命名空间

    使用System; 使用System.Data; 使用Microsoft.SqlServer.Dts.Runtime; 使用System.Windows.Forms; 使用System.IO;

    endregion

    命名空间ST_523853dfbc0d4123be43383671f8a6c6 {     [Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute]     public partial class ScriptMain:Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase     {         public void Main()         {             尝试             {                 bool fireAgain = false;                 string backupFolder = string.Empty;                 string backupFilePath = string.Empty;

                string sourcFilePath = Dts.Variables["User::Source_FilePath"].Value.ToString();
                string targetFolder = Dts.Variables["User::Target_Folder"].Value.ToString();
                string backupFolderName = Dts.Variables["User::Backup_FolderName"].Value.ToString();
    
                if (String.IsNullOrEmpty(sourcFilePath) || !File.Exists(sourcFilePath))
                {
                    // Check if a valid source file path was specified on the package variable
                    Dts.Events.FireError(101, "Source path error", String.Format("You need to set a valid source file path in the package variable 'Source_FilePath'. Invalid path: '{0}'", sourcFilePath), string.Empty, 0);
                    Dts.TaskResult = (int)ScriptResults.Failure;
                }
                else if (String.IsNullOrEmpty(targetFolder) || !Directory.Exists(targetFolder))
                {
                    // Check if a valid target folder was specified on the package variable
                    Dts.Events.FireError(102, "Target folder error", String.Format("You need to set a valid target folder location in the package variable 'Target_Folder'. Invalid folder: '{0}'", targetFolder), string.Empty, 0);
                    Dts.TaskResult = (int)ScriptResults.Failure;
                }
                else
                {
                    FileInfo sourceInfo = new FileInfo(sourcFilePath);
    
                    // Loop through each file that matches the name of the source file
                    foreach (string targetFilePath in Directory.EnumerateFiles(targetFolder, sourceInfo.Name, SearchOption.AllDirectories))
                    {
                        FileInfo targetInfo = new FileInfo(targetFilePath);
                        backupFolder = Path.Combine(targetInfo.Directory.FullName, backupFolderName);
                        backupFilePath = Path.Combine(backupFolder, backupFolderName);
    
                        // If the backup folder does not exist in the folder within root target folder, create the backup folder.
                        if (!Directory.Exists(backupFolder))
                        {
                            Directory.CreateDirectory(backupFolder);
                            Dts.Events.FireInformation(401, "Backup folder created", String.Format("Backup folder '{0}' was created.", backupFolder), string.Empty, 0, ref fireAgain);
                        }
    
                        // Archive the target file to the backup folder.
                        File.Copy(targetFilePath, backupFilePath, true);
                        Dts.Events.FireInformation(402, "Target file archived", String.Format("Target file '{0}' was archived to the backup folder '{1}'.", targetFilePath, backupFolder), string.Empty, 0, ref fireAgain);
    
                        // Overwrite the target file with the source file.
                        File.Copy(sourcFilePath, targetFilePath, true);
                        Dts.Events.FireInformation(403, "Target file overwritten", String.Format("Target file '{0}' was overwritten with the source file '{1}'.", sourcFilePath, targetFilePath), string.Empty, 0, ref fireAgain);
                    }
    
                    Dts.TaskResult = (int)ScriptResults.Success;
                }
            }
            catch (Exception ex)
            {
                Dts.Events.FireError(100, "Unhandled exception", ex.ToString(), string.Empty, 0);
            }
        }
    
        #region ScriptResults declaration
        enum ScriptResults
        {
            Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
            Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
        };
        #endregion
    }
    

    }

用于SSIS 2005及更高版本的VB.NET中的

脚本任务代码:

#Region "Imports"
Imports System
Imports System.Data
Imports System.Math
Imports System.IO
Imports Microsoft.SqlServer.Dts.Runtime
#End Region

<Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute()> _
<System.CLSCompliantAttribute(False)> _
Partial Public Class ScriptMain
    Inherits Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase

    Public Sub Main()

        Try
            Dim fireAgain As Boolean = False
            Dim backupFolder As String = String.Empty
            Dim backupFilePath As String = String.Empty

            Dim sourcFilePath As String = Dts.Variables("User::Source_FilePath").Value.ToString()
            Dim targetFolder As String = Dts.Variables("User::Target_Folder").Value.ToString()
            Dim backupFolderName As String = Dts.Variables("User::Backup_FolderName").Value.ToString()

            If String.IsNullOrEmpty(sourcFilePath) OrElse Not File.Exists(sourcFilePath) Then
                ' Check if a valid source file path was specified on the package variable
                Dts.Events.FireError(101, "Source path error", String.Format("You need to set a valid source file path in the package variable 'Source_FilePath'. Invalid path: '{0}'", sourcFilePath), String.Empty, 0)
                Dts.TaskResult = ScriptResults.Failure

            ElseIf String.IsNullOrEmpty(targetFolder) OrElse Not Directory.Exists(targetFolder) Then
                ' Check if a valid target folder was specified on the package variable
                Dts.Events.FireError(102, "Target folder error", String.Format("You need to set a valid target folder location in the package variable 'Target_Folder'. Invalid folder: '{0}'", targetFolder), String.Empty, 0)
                Dts.TaskResult = ScriptResults.Failure

            Else
                Dim sourceInfo As FileInfo = New FileInfo(sourcFilePath)

                ' Loop through each file that matches the name of the source file
                For Each targetFilePath As String In Directory.EnumerateFiles(targetFolder, sourceInfo.Name, SearchOption.AllDirectories)

                    Dim targetInfo As FileInfo = New FileInfo(targetFilePath)
                    backupFolder = Path.Combine(targetInfo.Directory.FullName, backupFolderName)
                    backupFilePath = Path.Combine(backupFolder, backupFolderName)

                    ' If the backup folder does not exist in the folder within root target folder, create the backup folder.
                    If Not Directory.Exists(backupFolder) Then
                        Directory.CreateDirectory(backupFolder)
                        Dts.Events.FireInformation(401, "Backup folder created", String.Format("Backup folder '{0}' was created.", backupFolder), String.Empty, 0, fireAgain)
                    End If

                    ' Archive the target file to the backup folder.
                    File.Copy(targetFilePath, backupFilePath, True)
                    Dts.Events.FireInformation(402, "Target file archived", String.Format("Target file '{0}' was archived to the backup folder '{1}'.", targetFilePath, backupFolder), String.Empty, 0, fireAgain)

                    ' Overwrite the target file with the source file.
                    File.Copy(sourcFilePath, targetFilePath, True)
                    Dts.Events.FireInformation(403, "Target file overwritten", String.Format("Target file '{0}' was overwritten with the source file '{1}'.", sourcFilePath, targetFilePath), String.Empty, 0, fireAgain)

                Next

                Dts.TaskResult = ScriptResults.Success

            End If

        Catch ex As Exception
            Dts.Events.FireError(100, "Unhandled exception", ex.ToString(), String.Empty, 0)
            Dts.TaskResult = ScriptResults.Failure
        End Try

    End Sub

#Region "ScriptResults declaration"
    Enum ScriptResults
        Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success
        Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
    End Enum

#End Region

End Class

当提供无效的源文件路径时,包将抛出以下错误消息:

Source file error

当提供无效的目标文件夹时,程序包将抛出以下错误消息:

Target file error

当源位置和目标位置有效时,包将成功执行。在这个例子中,

  • Target_1 下有一个备份文件夹,因此没有创建文件夹,但文件已复制到备份文件夹。
  • Target_2 中没有匹配的文件,因此未采取任何措施。
  • 备份文件夹是在 Target_3 中创建的,文件已复制到目标位置,然后被源文件覆盖。

Successful

文件夹结构(最终)

在程序包执行后,目标位置将如下所示。

Target
    |- Target_1
    |    |- Archive
    |        |- Sample_File.txt
    |    |- Sample_File.txt
    |- Target_2
    |- Target_3
        |- Archive
            |- Sample_File.txt
        |- Sample_File.txt

答案 1 :(得分:1)

显然@Siva's done tremendous work回答了你的问题。不过,我想知道以下情况是否会使这项工作更糟糕(尽管很可能并没有花费我很长时间来提出这个脚本):

@ECHO OFF

SET "srcname=target.file"
SET "srcpath=D:\path\to\source"
SET "tgtpath=\\remotehost\shared\folder"
SET "bakname=Backup"

FOR /D %%D IN ("%tgtpath%\*") DO (
  IF EXIST "%%D\%srcname%" (
    IF NOT EXIST "%%D\%bakname%" MKDIR "%%D\%bakname%"
    COPY /Y "%%D\%srcname%" "%%D\%bakname%"
    COPY /Y "%srcpath%\%srcname%" "%%D"
  )
)