AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Code-Bibliothek Neuen Beitrag zur Code-Library hinzufügen Delphi Background Intelligent Transfer Service nutzen
Thema durchsuchen
Ansicht
Themen-Optionen

Background Intelligent Transfer Service nutzen

Ein Thema von HeikoAdams · begonnen am 6. Aug 2010 · letzter Beitrag vom 11. Aug 2010
Antwort Antwort
Seite 1 von 3  1 23      
Benutzerbild von HeikoAdams
HeikoAdams

Registriert seit: 12. Jul 2004
Ort: Oberfranken
661 Beiträge
 
FreePascal / Lazarus
 
#1

Background Intelligent Transfer Service nutzen

  Alt 6. Aug 2010, 13:37
Hier mal eine selbstgeschriebene Klasse, zur Nutzung des Background Intelligent Transfer Service (BITS) von Windows:

Delphi-Quellcode:
unit RifBackgroundCopyService;

interface

uses ExtActns, JwaWindows, Types, SysUtils;

type
  EInitServiceError = Exception;
  TBackgroundCopyService = class
  private
    FAttempts: Byte;
    CopyMngr: IBackgroundCopyManager;
    CopyJob: IBackgroundCopyJob;

    function DownloadUrl(const aURL, aDest: WideString;
      const aDownloadFeedback: TDownloadProgressEvent; var aError: WideString;
      const aDisplayName: WideString;
      const aJobType: BG_JOB_TYPE = BG_JOB_TYPE_DOWNLOAD): Boolean;
    function DownloadMultiUrl(const aURL, aDest: TWideStringDynArray;
      const aDownloadFeedback: TDownloadProgressEvent; var aError: WideString;
      const aDisplayName: WideString;
      const aJobType: BG_JOB_TYPE = BG_JOB_TYPE_DOWNLOAD): Boolean;

    function WaitForDownload(const aJobType: BG_JOB_TYPE; var aError: WideString;
      const aDownloadFeedback: TDownloadProgressEvent): BG_JOB_STATE;
    function GetNewJob(const aDisplayName: WideString;
      const aJobType: BG_JOB_TYPE; var aJob: IBackgroundCopyJob): Integer;
    function GetCopyJobError: WideString;
    function ResumeJob(const aJobType: BG_JOB_TYPE; const aDownloadFeedback: TDownloadProgressEvent;
      var aError: WideString): Boolean;
  public
    constructor Create;
    destructor Destroy; override;

    function UploadFile(const aURL, aDest: WideString;
      const aDownloadFeedback: TDownloadProgressEvent; var aError: WideString;
      const aDisplayName: WideString): Boolean;
    function DownloadFile(const aURL, aDest: WideString;
      const aDownloadFeedback: TDownloadProgressEvent; var aError: WideString;
      const aDisplayName: WideString): Boolean;
    function DownloadFiles(const aURL, aDest: TWideStringDynArray;
      const aDownloadFeedback: TDownloadProgressEvent; var aError: WideString;
      const aDisplayName: WideString): Boolean;

    property AttemptsOnFailure: Byte read FAttempts write FAttempts;
  end;

implementation

uses JclWin32, ComObj, JclSysInfo;

constructor TBackgroundCopyService.Create();
begin
  FAttempts := 3;
  CopyMngr := CreateComObject(CLSID_BackgroundCopyManager) as IBackgroundCopyManager;

  if not Assigned(CopyMngr) then
    raise EInitServiceError.Create('Initialization of BackgroundCopyService failed!');
end;

destructor TBackgroundCopyService.Destroy;
begin
  inherited;

  if Assigned(CopyJob) then
    CopyJob := nil;

  if Assigned(CopyMngr) then
    CopyMngr := nil;
end;

function TBackgroundCopyService.UploadFile(const aURL, aDest: WideString;
  const aDownloadFeedback: TDownloadProgressEvent; var aError: WideString;
  const aDisplayName: WideString): Boolean;
var
  nCount: Byte;
begin
  nCount := 1;

  repeat
    Result := DownloadUrl(aURL, aDest, aDownloadFeedback, aError, aDisplayName,
      BG_JOB_TYPE_UPLOAD);

    Inc(nCount);
  until Result or (nCount > FAttempts);
end;

function TBackgroundCopyService.DownloadFile(const aURL, aDest: WideString;
  const aDownloadFeedback: TDownloadProgressEvent; var aError: WideString;
  const aDisplayName: WideString): Boolean;
var
  nCount: Byte;
begin
  nCount := 1;

  repeat
    Result := DownloadUrl(aURL, aDest, aDownloadFeedback, aError, aDisplayName,
      BG_JOB_TYPE_DOWNLOAD);

    Inc(nCount);
  until Result or (nCount > FAttempts);
end;

function TBackgroundCopyService.DownloadFiles(const aURL, aDest: TWideStringDynArray;
  const aDownloadFeedback: TDownloadProgressEvent; var aError: WideString;
  const aDisplayName: WideString): Boolean;
var
  nCount: Byte;
begin
  nCount := 1;

  repeat
    Result := DownloadMultiUrl(aURL, aDest, aDownloadFeedback, aError,
      aDisplayName, BG_JOB_TYPE_DOWNLOAD);

    Inc(nCount);
  until Result or (nCount > FAttempts);
end;

function TBackgroundCopyService.GetNewJob(const aDisplayName: WideString;
  const aJobType: BG_JOB_TYPE; var aJob: IBackgroundCopyJob): Integer;
var
  JobId: TGUID;
begin
  Result := CopyMngr.CreateJob(PWideChar(aDisplayName), aJobType, JobId, aJob);
end;

function TBackgroundCopyService.GetCopyJobError: WideString;
var
  CopyError: IBackgroundCopyError;
  sTemp: PWideChar;
begin
  CopyJob.GetError(CopyError);
  CopyError.GetErrorDescription(LANGIDFROMLCID(GetThreadLocale()), sTemp);
  CopyError := nil;

  Result := WideString(WideCharToString(sTemp));
end;

function TBackgroundCopyService.ResumeJob(const aJobType: BG_JOB_TYPE;
  const aDownloadFeedback: TDownloadProgressEvent; var aError: WideString): Boolean;
var
  JobStatus: BG_JOB_STATE;
begin
  Result := False;

  CopyJob.Resume();

  JobStatus := WaitForDownload(aJobType, aError, aDownloadFeedback);

  if (JobStatus in [BG_JOB_STATE_TRANSFERRED,
    BG_JOB_STATE_ERROR, BG_JOB_STATE_TRANSIENT_ERROR]) then
  begin
    Result := (JobStatus = BG_JOB_STATE_TRANSFERRED);

    if not Result then
      aError := GetCopyJobError;
  end;

  if (JobStatus = BG_JOB_STATE_TRANSFERRED) then
    CopyJob.Complete
  else
    CopyJob.Cancel;
end;

function TBackgroundCopyService.DownloadUrl(const aURL, aDest: WideString;
  const aDownloadFeedback: TDownloadProgressEvent; var aError: WideString;
  const aDisplayName: WideString;
  const aJobType: BG_JOB_TYPE = BG_JOB_TYPE_DOWNLOAD): Boolean;
var
  Res: HRESULT;
begin
  if Assigned(CopyJob) then
    CopyJob := nil;
    
  Result := False;
  Res := GetNewJob(PWideChar(aDisplayName), aJobType, CopyJob);

  if not Succeeded(Res) then
  begin
    aError := WideString(SysErrorMessage(Res));
    Exit;
  end;

  Res := CopyJob.AddFile(PWideChar(aURL), PWideChar(aDest));

  if not Succeeded(Res) then
  begin
    aError := WideString(SysErrorMessage(Res));
    Exit;
  end;

  Result := ResumeJob(aJobType, aDownloadFeedback, aError);
  CopyJob := nil;
end;

function TBackgroundCopyService.DownloadMultiUrl(const aURL, aDest: TWideStringDynArray;
  const aDownloadFeedback: TDownloadProgressEvent; var aError: WideString;
  const aDisplayName: WideString;
  const aJobType: BG_JOB_TYPE = BG_JOB_TYPE_DOWNLOAD): Boolean;
var
  DownloadInfo: PBgFileInfo;
  Res: HRESULT;
  nCount: Integer;
begin
  if Assigned(CopyJob) then
    CopyJob := nil;

  Result := False;
  Res := GetNewJob(PWideChar(aDisplayName), aJobType, CopyJob);

  if not Succeeded(Res) then
  begin
    aError := WideString(SysErrorMessage(Res));
    Exit;
  end;

  ZeroMemory(@DownloadInfo, SizeOf(DownloadInfo));

  for nCount := Low(aURL) to High(aURL) do
  begin
    DownloadInfo.RemoteName := PWideChar(aUrl[nCount]);
    DownloadInfo.LocalName := PWideChar(aDest[nCount]);
  end;

  nCount := Length(aURL);
  Res := CopyJob.AddFileSet(nCount, DownloadInfo);

  if not Succeeded(Res) then
  begin
    aError := WideString(SysErrorMessage(Res));
    Exit;
  end;

  Result := ResumeJob(aJobType, aDownloadFeedback, aError);
  CopyJob := nil;
end;

function TBackgroundCopyService.WaitForDownload(const aJobType: BG_JOB_TYPE;
  var aError: WideString; const aDownloadFeedback: TDownloadProgressEvent): BG_JOB_STATE;
var
  JobProgress: BG_JOB_PROGRESS;
  hTimer: THandle;
  DueTime: TLargeInteger;
  bCanceled: boolean;
begin
  bCanceled := False;
  DueTime := -10000000;
  hTimer := CreateWaitableTimer(nil, false, 'EinTimer');
  SetWaitableTimer(hTimer, DueTime, 1000, nil, nil, false);

  while True do
  begin
    CopyJob.GetState(Result);

    if (Result in [BG_JOB_STATE_TRANSFERRING, BG_JOB_STATE_TRANSFERRED]) then
    begin
      CopyJob.GetProgress(JobProgress);

      if (aJobType = BG_JOB_TYPE_DOWNLOAD) then
        aDownloadFeedback(nil, JobProgress.BytesTransferred, JobProgress.BytesTotal,
          dsDownloadingData, '', bCanceled)
      else
        aDownloadFeedback(nil, JobProgress.BytesTransferred, JobProgress.BytesTotal,
          dsUploadingData, '', bCanceled);

      if bCanceled then
        break;
    end;

    if (Result in [BG_JOB_STATE_TRANSFERRED,
      BG_JOB_STATE_ERROR, BG_JOB_STATE_TRANSIENT_ERROR]) then
      break;

    WaitForSingleObject(hTimer, INFINITE);
  end;

  CancelWaitableTimer(hTimer);
  CloseHandle(hTimer);
end;

end.
Wie unschwer zu erkennen ist, werden die Jedi API-Header benötigt.
Jeder kann ein Held werden und Leben retten!
Einfach beim NKR oder der DKMS als Stammzellenspender registrieren! Also: worauf wartest Du noch?

Geändert von HeikoAdams ( 6. Aug 2010 um 15:24 Uhr)
  Mit Zitat antworten Zitat
Dezipaitor

Registriert seit: 14. Apr 2003
Ort: Stuttgart
1.701 Beiträge
 
Delphi 7 Professional
 
#2

AW: Background Intelligent Transfer Service nutzen

  Alt 6. Aug 2010, 14:54
Warum nutzt du PWideChar überhaupt?

aError := PWideChar(WideString(SysErrorMessage(Res)));
Christian
Windows, Tokens, Access Control List, Dateisicherheit, Desktop, Vista Elevation?
Goto: JEDI API LIB & Windows Security Code Library (JWSCL)
  Mit Zitat antworten Zitat
Benutzerbild von HeikoAdams
HeikoAdams

Registriert seit: 12. Jul 2004
Ort: Oberfranken
661 Beiträge
 
FreePascal / Lazarus
 
#3

AW: Background Intelligent Transfer Service nutzen

  Alt 6. Aug 2010, 15:04
reine Bequemlichkeit. Habs aber trotzdem mal auf WideString als Datentyp für aError geändert
Jeder kann ein Held werden und Leben retten!
Einfach beim NKR oder der DKMS als Stammzellenspender registrieren! Also: worauf wartest Du noch?

Geändert von HeikoAdams ( 6. Aug 2010 um 15:13 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.136 Beiträge
 
Delphi 12 Athens
 
#4

AW: Background Intelligent Transfer Service nutzen

  Alt 6. Aug 2010, 15:14
Zitat:
Delphi-Quellcode:
function TBackgroundCopyService.DownloadMultiUrl(const aURL, aDest: TWideStringDynArray;
  const aDownloadFeedback: TDownloadProgressEvent; var aError: PWideChar;
  const aDisplayName: PWideChar;
  const aJobType: BG_JOB_TYPE = BG_JOB_TYPE_DOWNLOAD): Boolean;

begin
  
  aError := PWideChar(WideString(SysErrorMessage(Res)));
Du weißt aber, daß das Ergebnis der WideString-Konvertierung in einer temporären und vorallem lokalen variable abgelegt wird, bevor davon via PWideChar ein Zeiger darauf besorgt wird.
Diese Variable wird beim verlassen der Prozedur freigegeben und somit zeigt der PWideChar ins "Nichts".
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu ( 6. Aug 2010 um 15:52 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von HeikoAdams
HeikoAdams

Registriert seit: 12. Jul 2004
Ort: Oberfranken
661 Beiträge
 
FreePascal / Lazarus
 
#5

AW: Background Intelligent Transfer Service nutzen

  Alt 6. Aug 2010, 15:20
Habs schon geändert. Alle Parameter sind in WideString geändert.
Jeder kann ein Held werden und Leben retten!
Einfach beim NKR oder der DKMS als Stammzellenspender registrieren! Also: worauf wartest Du noch?

Geändert von HeikoAdams ( 6. Aug 2010 um 15:25 Uhr)
  Mit Zitat antworten Zitat
Dezipaitor

Registriert seit: 14. Apr 2003
Ort: Stuttgart
1.701 Beiträge
 
Delphi 7 Professional
 
#6

AW: Background Intelligent Transfer Service nutzen

  Alt 6. Aug 2010, 15:48
Wäre eh besser
raiseLastOSError zu verwenden, als einen FehlerSTRING zurückzugeben, den man nicht nutzen kann, um auf einen Fehler im Programmcode zu reagieren.
Christian
Windows, Tokens, Access Control List, Dateisicherheit, Desktop, Vista Elevation?
Goto: JEDI API LIB & Windows Security Code Library (JWSCL)
  Mit Zitat antworten Zitat
generic

Registriert seit: 24. Mär 2004
Ort: bei Hannover
2.415 Beiträge
 
Delphi XE5 Professional
 
#7

AW: Background Intelligent Transfer Service nutzen

  Alt 6. Aug 2010, 15:55
Hast du dich etwa vom aktuellen Entwickler Magazin inspirieren
lassen?
Dort ist im Uptodate Artikel auch was zum BITs drin.
Dein Source sieht an manchen stellen sehr sehr ähnlich aus.

Coding BOTT - Video Tutorials rund um das Programmieren - https://www.youtube.com/@codingbott
  Mit Zitat antworten Zitat
Benutzerbild von HeikoAdams
HeikoAdams

Registriert seit: 12. Jul 2004
Ort: Oberfranken
661 Beiträge
 
FreePascal / Lazarus
 
#8

AW: Background Intelligent Transfer Service nutzen

  Alt 6. Aug 2010, 16:00
Sagen wir mal, ich habe den Source aus dem Entwicklermagazin als Grundlage genutzt und (hoffentlich) sinnvoll ergänzt und erweitert
Jeder kann ein Held werden und Leben retten!
Einfach beim NKR oder der DKMS als Stammzellenspender registrieren! Also: worauf wartest Du noch?
  Mit Zitat antworten Zitat
Benutzerbild von HeikoAdams
HeikoAdams

Registriert seit: 12. Jul 2004
Ort: Oberfranken
661 Beiträge
 
FreePascal / Lazarus
 
#9

AW: Background Intelligent Transfer Service nutzen

  Alt 6. Aug 2010, 16:04
Wäre eh besser raiseLastOSError zu verwenden, als einen FehlerSTRING zurückzugeben, den man nicht nutzen kann, um auf einen Fehler im Programmcode zu reagieren.
Du immer mit Deinen Exceptions Ich halte nicht viel davon, bei jedem Fehler eine Exception zu werfen. Einen aussagekräftigen Returncode bzw. eine eindeutige Fehlermeldung halte ich für viel hilfreicher. Immerhin kann man so die aufgerufene Prozedur/Funktion kontrolliert beenden.
Jeder kann ein Held werden und Leben retten!
Einfach beim NKR oder der DKMS als Stammzellenspender registrieren! Also: worauf wartest Du noch?
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.136 Beiträge
 
Delphi 12 Athens
 
#10

AW: Background Intelligent Transfer Service nutzen

  Alt 6. Aug 2010, 16:26
Immerhin kann man so die aufgerufene Prozedur/Funktion kontrolliert beenden.
Try-Except/Finally?

Und man kann auch einen nummerischen Fehlercode in der Exception hinterlegen.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:21 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz