在SQL SERVER中要进行大数据量的复制或在两台机器中进行大数据量的复制,最好的工具是DTS.如何在Delphi中调用DTS,笔者经查阅网上资料,参照相关代码终于搞定。再次代码贴出来,希望能够给有这个方面需求的人所有帮助,同时也感谢delphibbs上的好人。

    

unit uFrmMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, OleServer, DTS_TLB, DTSEvents, StdCtrls;

type
  TFrmMain = class(TForm)
    btnLoadFile: TButton;
    dlgOpen1: TOpenDialog;
    edtFileName: TEdit;
    lbl1: TLabel;
    btnExecute: TButton;
    mmoInfo: TMemo;
    procedure btnExecuteClick(Sender: TObject);
    procedure btnLoadFileClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    oPackage: Package;
   
    procedure AddItem(AText: string);
    procedure RunPackage(AFileName: string);
    function InternalPackageStartEvent(Sender: TObject; const EventSource: WideString): HResult;
    function InternalPackageFinishEvent(Sender: TObject; const EventSource: WideString): HResult;
    function InternalPackageErrorEvent(Sender: TObject; const EventSource: WideString;
      ErrorCode: Integer; const Source: WideString; const Description: WideString;
      const HelpFile: WideString; HelpContext: Integer;
      const IDofInterfaceWithError: WideString;
      var pbCancel: WordBool): HResult;
    function InternalPackageProgressEvent(Sender: TObject;
      const EventSource: WideString; const ProgressDescription: WideString;
      PercentComplete: Integer; ProgressCountLow: Integer;
      ProgressCountHigh: Integer): HResult;
    function InternalPackageQueryCancelEvent(Sender: TObject;
      const EventSource: WideString; var pbCancel: WordBool): HResult;
    function GetDTSError(APackage: Package): string;
  public
    { Public declarations }
  end;

var
  FrmMain: TFrmMain;

implementation


{$R *.dfm}

procedure TFrmMain.AddItem(AText: string);
begin
  mmoInfo.Lines.Add(DateTimeToStr(Now) + ' ' + AText)
end;

procedure TFrmMain.RunPackage(AFileName: string);
var
  oStep: Step;
  oTask: Task;
  oExecPkg: ExecutePackageTask;
  oDTSEvent: TDTSPackageEvents;
begin
  oStep := oPackage.Steps.New;
  oTask := oPackage.Tasks.New('DTSExecutePackageTask');
  oExecPkg := ExecutePackageTask(oTask.CustomTask);
  with oExecPkg do
  begin
    Name := 'ExecPkgTask';
    ServerName := '(local)';
    UseTrustedConnection := True;
    //Use something like this for non NT authentication
    //ServerUserName = "sa"
    //ServerPassword = 'Request this password, don't include it in code
    FileName := AFileName;
  end;

  with oStep do
  begin
    TaskName := oExecPkg.Name;
    Name := 'ExecPkgStep';
    ExecuteInMainThread := False;
  end;
  oPackage.Steps.Add(oStep);
  oPackage.Tasks.Add(oTask);
  oDTSEvent := TDTSPackageEvents.Create(nil);
  oDTSEvent.OnStart := InternalPackageStartEvent;
  oDTSEvent.OnFinish := InternalPackageFinishEvent;
  oDTSEvent.OnError := InternalPackageErrorEvent;
  oDTSEvent.OnProgress := InternalPackageProgressEvent;
  oDTSEvent.OnQueryCancel := InternalPackageQueryCancelEvent;
  oDTSEvent.Connect(oPackage);
  oPackage.Execute;
  oExecPkg := nil;
  oTask := nil;
  oStep := nil;
  oPackage.UnInitialize;
end;

procedure TFrmMain.btnExecuteClick(Sender: TObject);
begin
  RunPackage(edtFileName.Text);
end;

procedure TFrmMain.btnLoadFileClick(Sender: TObject);
begin
  if dlgOpen1.Execute then
  begin
    edtFileName.Text := dlgOpen1.FileName;
    btnExecute.Enabled := True;
  end;
end;

procedure TFrmMain.FormCreate(Sender: TObject);
begin
  oPackage := CoPackage.Create;
end;

function TFrmMain.InternalPackageErrorEvent(Sender: TObject;
  const EventSource: WideString; ErrorCode: Integer; const Source,
  Description, HelpFile: WideString; HelpContext: Integer;
  const IDofInterfaceWithError: WideString;
  var pbCancel: WordBool): HResult;
begin
  AddItem(EventSource + ' Error: ' + GetDTSError(oPackage));
  Result := S_OK;
end;

function TFrmMain.InternalPackageFinishEvent(Sender: TObject;
  const EventSource: WideString): HResult;
begin
  AddItem(EventSource + ' Finished');
  Result := S_OK;
end;

function TFrmMain.InternalPackageProgressEvent(Sender: TObject;
  const EventSource, ProgressDescription: WideString; PercentComplete,
  ProgressCountLow, ProgressCountHigh: Integer): HResult;
begin
  AddItem(Format(EventSource + ' Progress %d/%d %d', [PercentComplete, ProgressCountLow,
    ProgressCountHigh]));
  Result := S_OK;
end;

function TFrmMain.InternalPackageQueryCancelEvent(Sender: TObject;
  const EventSource: WideString; var pbCancel: WordBool): HResult;
begin
  AddItem(EventSource + ' QueryCancel');
  Result := S_OK;
end;

function TFrmMain.InternalPackageStartEvent(Sender: TObject;
  const EventSource: WideString): HResult;
begin
  AddItem(EventSource + ' Start');
  Result := S_OK;
end;

function TFrmMain.GetDTSError(APackage: Package): string;
var
  I: Integer;
  iErrNum: Integer;
  sDescr: WideString;
  sSource: WideString;
  sHelpFile: WideString;
  iHelpContext: Integer;
  sError: WideString;
begin
  Result := '';

  for I := 1 to APackage.Steps.Count do
  begin
    with APackage.Steps.Item(I) do
    begin
      if ExecutionStatus = DTSStepExecStat_Completed then
      begin
        if ExecutionResult = DTSStepExecResult_Failure then
          GetExecutionErrorInfo(iErrNum, sSource, sDescr, sHelpFile,
            iHelpContext, sError);
          Result := Result + #13#10 +
            '步骤:' + Name + '出错,错误代码:' + IntToHex(iErrNum, 8) + #13#10 +
            '描述:' + sDescr;
      end;
    end;
  end;
end;

end.

 

/*   DTS Event 单元  */

{ *******************

**********************************************************
  WARNING: This component file was generated using the EventSinkImp utility.
           The contents of this file will be overwritten everytime EventSinkImp
           is asked to regenerate this sink component.

  NOTE:    When using this component at the same time with the XXX_TLB.pas in
           your Delphi projects, make sure you always put the XXX_TLB unit name
           AFTER this component unit name in the USES clause of the interface
           section of your unit; otherwise you may get interface conflict
           errors from the Delphi compiler.

           EventSinkImp is written by Binh Ly (bly@techvanguards.com)
  *****************************************************************************
  //Sink Classes//
  TDTSPackageEvents
}

{$IFDEF VER100}
{$DEFINE D3}
{$ENDIF}

//SinkUnitName//
unit DTSEvents;

interface

uses
  Windows, ActiveX, Classes, ComObj, OleCtrls
  //SinkUses//
  , StdVCL
  , DTS_TLB
  ;

type
  { backward compatibility types }
  {$IFDEF D3}
  OLE_COLOR = TOleColor;
  {$ENDIF}

  TDTSEventsBaseSink = class (TComponent, IUnknown, IDispatch)
  protected
    { IUnknown }
    function QueryInterface(const IID: TGUID; out Obj): HResult; {$IFNDEF D3} override; {$ENDIF} stdcall;
    function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;

    { IDispatch }
    function GetIDsOfNames(const IID: TGUID; Names: Pointer;
      NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; virtual; stdcall;
    function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; virtual; stdcall;
    function GetTypeInfoCount(out Count: Integer): HResult; virtual; stdcall;
    function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
      Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; virtual; stdcall;
  protected
    FCookie: integer;
    FCP: IConnectionPoint;
    FSinkIID: TGUID;
    FSource: IUnknown;
    function DoInvoke (DispID: Integer; const IID: TGUID; LocaleID: Integer;
      Flags: Word; var dps: TDispParams; pDispIds: PDispIdList;
      VarResult, ExcepInfo, ArgErr: Pointer): HResult; virtual; abstract;
  public
    destructor Destroy; override;
    procedure Connect (const ASource: IUnknown);
    procedure Disconnect;
    property SinkIID: TGUID read FSinkIID write FSinkIID;
    property Source: IUnknown read FSource;
  end;

  //SinkImportsForwards//

  //SinkImports//

  //SinkIntfStart//

  //SinkEventsForwards//
  TPackageEventsOnStartEvent = function  (Sender: TObject; const EventSource: WideString): HResult of object;
  TPackageEventsOnFinishEvent = function  (Sender: TObject; const EventSource: WideString): HResult of object;
  TPackageEventsOnErrorEvent = function  (Sender: TObject; const EventSource: WideString; ErrorCode: Integer; const Source: WideString; const Description: WideString; const HelpFile: WideString; HelpContext: Integer; const IDofInterfaceWithError: WideString; var pbCancel: WordBool): HResult of object;
  TPackageEventsOnProgressEvent = function  (Sender: TObject; const EventSource: WideString; const ProgressDescription: WideString; PercentComplete: Integer; ProgressCountLow: Integer; ProgressCountHigh: Integer): HResult of object;
  TPackageEventsOnQueryCancelEvent = function  (Sender: TObject; const EventSource: WideString; var pbCancel: WordBool): HResult of object;

  //SinkComponent//
  TDTSPackageEvents = class (TDTSEventsBaseSink  , PackageEvents)
  protected
    function DoInvoke (DispID: Integer; const IID: TGUID; LocaleID: Integer;
      Flags: Word; var dps: TDispParams; pDispIds: PDispIdList;
      VarResult, ExcepInfo, ArgErr: Pointer): HResult; override;

    { PackageEvents }
    function PackageEvents.OnStart = DoOnStart;
    function PackageEvents.OnFinish = DoOnFinish;
    function PackageEvents.OnError = DoOnError;
    function PackageEvents.OnProgress = DoOnProgress;
    function PackageEvents.OnQueryCancel = DoOnQueryCancel;
  public
    { system methods }
    constructor Create (AOwner: TComponent); override;
  protected
    //SinkInterface//
    function  DoOnStart(const EventSource: WideString): HResult; stdcall;
    function  DoOnFinish(const EventSource: WideString): HResult; stdcall;
    function  DoOnError(const EventSource: WideString; ErrorCode: Integer; const Source: WideString; const Description: WideString; const HelpFile: WideString; HelpContext: Integer; const IDofInterfaceWithError: WideString; var pbCancel: WordBool): HResult; stdcall;
    function  DoOnProgress(const EventSource: WideString; const ProgressDescription: WideString; PercentComplete: Integer; ProgressCountLow: Integer; ProgressCountHigh: Integer): HResult; stdcall;
    function  DoOnQueryCancel(const EventSource: WideString; var pbCancel: WordBool): HResult; stdcall;
  protected
    //SinkEventsProtected//
    FOnStart: TPackageEventsOnStartEvent;
    FOnFinish: TPackageEventsOnFinishEvent;
    FOnError: TPackageEventsOnErrorEvent;
    FOnProgress: TPackageEventsOnProgressEvent;
    FOnQueryCancel: TPackageEventsOnQueryCancelEvent;
  published
    //SinkEventsPublished//
    property OnStart: TPackageEventsOnStartEvent read FOnStart write FOnStart;
    property OnFinish: TPackageEventsOnFinishEvent read FOnFinish write FOnFinish;
    property OnError: TPackageEventsOnErrorEvent read FOnError write FOnError;
    property OnProgress: TPackageEventsOnProgressEvent read FOnProgress write FOnProgress;
    property OnQueryCancel: TPackageEventsOnQueryCancelEvent read FOnQueryCancel write FOnQueryCancel;
  end;

  //SinkIntfEnd//

procedure Register;

implementation

uses
  SysUtils;

{ globals }

procedure BuildPositionalDispIds (pDispIds: PDispIdList; const dps: TDispParams);
var
  i: integer;
begin
  Assert (pDispIds <> nil);
 
  { by default, directly arrange in reverse order }
  for i := 0 to dps.cArgs - 1 do
    pDispIds^ [i] := dps.cArgs - 1 - i;

  { check for named args }
  if (dps.cNamedArgs <= 0) then Exit;

  { parse named args }
  for i := 0 to dps.cNamedArgs - 1 do
    pDispIds^ [dps.rgdispidNamedArgs^ [i]] := i;
end;


{ TDTSEventsBaseSink }

function TDTSEventsBaseSink.GetIDsOfNames(const IID: TGUID; Names: Pointer;
  NameCount, LocaleID: Integer; DispIDs: Pointer): HResult;
begin
  Result := E_NOTIMPL;
end;

function TDTSEventsBaseSink.GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult;
begin
  Result := E_NOTIMPL;
  pointer (TypeInfo) := nil;
end;

function TDTSEventsBaseSink.GetTypeInfoCount(out Count: Integer): HResult;
begin
  Result := E_NOTIMPL;
  Count := 0;
end;

function TDTSEventsBaseSink.Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
  Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult;
var
  dps: TDispParams absolute Params;
  bHasParams: boolean;
  pDispIds: PDispIdList;
  iDispIdsSize: integer;
begin
  { validity checks }
  if (Flags AND DISPATCH_METHOD = 0) then
    raise Exception.Create (
      Format ('%s only supports sinking of method calls!', [ClassName]
    ));

  { build pDispIds array. this maybe a bit of overhead but it allows us to
    sink named-argument calls such as Excel's AppEvents, etc!
  }
  pDispIds := nil;
  iDispIdsSize := 0;
  bHasParams := (dps.cArgs > 0);
  if (bHasParams) then
  begin
    iDispIdsSize := dps.cArgs * SizeOf (TDispId);
    GetMem (pDispIds, iDispIdsSize);
  end;  { if }

  try
    { rearrange dispids properly }
    if (bHasParams) then BuildPositionalDispIds (pDispIds, dps);
    Result := DoInvoke (DispId, IID, LocaleID, Flags, dps, pDispIds, VarResult, ExcepInfo, ArgErr);
  finally
    { free pDispIds array }
    if (bHasParams) then FreeMem (pDispIds, iDispIdsSize);
  end;  { finally }
end;

function TDTSEventsBaseSink.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
  if (GetInterface (IID, Obj)) then
  begin
    Result := S_OK;
    Exit;
  end
  else
    if (IsEqualIID (IID, FSinkIID)) then
      if (GetInterface (IDispatch, Obj)) then
      begin
        Result := S_OK;
        Exit;
      end;
  Result := E_NOINTERFACE;
  pointer (Obj) := nil;
end;

function TDTSEventsBaseSink._AddRef: Integer;
begin
  Result := 2;
end;

function TDTSEventsBaseSink._Release: Integer;
begin
  Result := 1;
end;

destructor TDTSEventsBaseSink.Destroy;
begin
  Disconnect;
  inherited;
end;

procedure TDTSEventsBaseSink.Connect (const ASource: IUnknown);
var
  pcpc: IConnectionPointContainer;
begin
  Assert (ASource <> nil);
  Disconnect;
  try
    OleCheck (ASource.QueryInterface (IConnectionPointContainer, pcpc));
    OleCheck (pcpc.FindConnectionPoint (FSinkIID, FCP));
    OleCheck (FCP.Advise (Self, FCookie));
    FSource := ASource;
  except
    raise Exception.Create (Format ('Unable to connect %s.'#13'%s',
      [Name, Exception (ExceptObject).Message]
    ));
  end;  { finally }
end;

procedure TDTSEventsBaseSink.Disconnect;
begin
  if (FSource = nil) then Exit;
  try
    OleCheck (FCP.Unadvise (FCookie));
    FCP := nil;
    FSource := nil;
  except
    pointer (FCP) := nil;
    pointer (FSource) := nil;
  end;  { except }
end;


//SinkImplStart//

function TDTSPackageEvents.DoInvoke (DispID: Integer; const IID: TGUID; LocaleID: Integer;
  Flags: Word; var dps: TDispParams; pDispIds: PDispIdList;
  VarResult, ExcepInfo, ArgErr: Pointer): HResult;
type
  POleVariant = ^OleVariant;
begin
  Result := DISP_E_MEMBERNOTFOUND;

  //SinkInvoke//
  //SinkInvokeEnd//
end;

constructor TDTSPackageEvents.Create (AOwner: TComponent);
begin
  inherited Create (AOwner);
  //SinkInit//
  FSinkIID := PackageEvents;
end;

//SinkImplementation//
function  TDTSPackageEvents.DoOnStart(const EventSource: WideString): HResult;
begin
  Result := S_OK;
  if not Assigned (OnStart) then System.Exit;
  Result := OnStart (Self, EventSource);
end;

function  TDTSPackageEvents.DoOnFinish(const EventSource: WideString): HResult;
begin
  Result := S_OK;
  if not Assigned (OnFinish) then System.Exit;
  Result := OnFinish (Self, EventSource);
end;

function  TDTSPackageEvents.DoOnError(const EventSource: WideString; ErrorCode: Integer; const Source: WideString; const Description: WideString; const HelpFile: WideString; HelpContext: Integer; const IDofInterfaceWithError: WideString; var pbCancel: WordBool): HResult;
begin
  Result := S_OK;
  if not Assigned (OnError) then System.Exit;
  Result := OnError (Self, EventSource, ErrorCode, Source, Description, HelpFile, HelpContext, IDofInterfaceWithError, pbCancel);
end;

function  TDTSPackageEvents.DoOnProgress(const EventSource: WideString; const ProgressDescription: WideString; PercentComplete: Integer; ProgressCountLow: Integer; ProgressCountHigh: Integer): HResult;
begin
  Result := S_OK;
  if not Assigned (OnProgress) then System.Exit;
  Result := OnProgress (Self, EventSource, ProgressDescription, PercentComplete, ProgressCountLow, ProgressCountHigh);
end;

function  TDTSPackageEvents.DoOnQueryCancel(const EventSource: WideString; var pbCancel: WordBool): HResult;
begin
  Result := S_OK;
  if not Assigned (OnQueryCancel) then System.Exit;
  Result := OnQueryCancel (Self, EventSource, pbCancel);
end;


//SinkImplEnd//

procedure Register;
begin
  //SinkRegisterStart//
  RegisterComponents ('ActiveX', [TDTSPackageEvents]);
  //SinkRegisterEnd//
end;

end.

 

/*  DFM文件 */

object FrmMain: TFrmMain
  Left = 192
  Top = 156
  BorderIcons = [biSystemMenu, biMinimize]
  BorderStyle = bsSingle
  Caption = 'DTS Demo App'
  ClientHeight = 566
  ClientWidth = 792
  Color = clBtnFace
  Font.Charset = ANSI_CHARSET
  Font.Color = clWindowText
  Font.Height = -15
  Font.Name = '宋体'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 15
  object lbl1: TLabel
    Left = 16
    Top = 29
    Width = 32
    Height = 15
    Caption = 'File'
  end
  object btnLoadFile: TButton
    Left = 704
    Top = 24
    Width = 75
    Height = 25
    Caption = 'Load'
    TabOrder = 0
    OnClick = btnLoadFileClick
  end
  object edtFileName: TEdit
    Left = 72
    Top = 25
    Width = 625
    Height = 23
    Enabled = False
    TabOrder = 1
  end
  object btnExecute: TButton
    Left = 704
    Top = 56
    Width = 75
    Height = 25
    Caption = 'Execute'
    Enabled = False
    TabOrder = 2
    OnClick = btnExecuteClick
  end
  object mmoInfo: TMemo
    Left = 16
    Top = 64
    Width = 673
    Height = 481
    ScrollBars = ssVertical
    TabOrder = 3
  end
  object dlgOpen1: TOpenDialog
    DefaultExt = '*.dts'
    Filter = 'DTS包(*.dts)|*.dts|所有文件|*.*'
    Left = 464
    Top = 312
  end
end

posted on 2010-12-07 00:22  bigshot  阅读(394)  评论(0编辑  收藏  举报