FastReport w Usłudze - czy działa?

0

Witam,
Czy używał ktoś Fast Report w usłudze?
Napisałem program, który generuje plik PDF.
Gdy chcę go zastosować w usłudze, to niestety nie działa.
Pytanie czy jest to możliwe? Jeżeli tak to może potrzebne są jakieś biblioteki?
Ma ktoś w tym doświadczenie?
Program ponadto dodaje informacje o dacie do pliku.txt.
Mamy metodę wątku

T_BezWatku.ServiceExecute(Sender: TService);

w której wywoływana jest metoda generująca plik PDF

report.PreviewReport(1); --Parametr zbędny

oraz zapis daty do pliku *.txt

 _BezWatku.InsertInFile;

Przy uruchomieniu usługi, data jest zapisywana cały czas do pliku, a plik PDF nie jest generowany.
PONADTO nie mogę wyłączyć usługi. Przy pierwszej próbie zatrzymania stan jest cały czas "Uruchomiony" a przy następnej otrzymuję bład.

screenshot-20171220152724.png

Jeżeli ktoś wie coś na temat używania FastReport w usłudze (Delphi) proszę o informację.

KOD:

unit MyServiceGood;

interface

uses
   Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs,
    ExtCtrls, DB, ADODB, DBTables,ActiveX, frxClass, frxExportPDF,frxDBSet,frxBarcode ;

type

  TReportEngine = class(TObject)
  private
    procedure detalAfterScroll(DataSet: TDataSet);
  protected
    _showProps:boolean;
    procedure setVisible(_obj:WideString;param:boolean);
    procedure setHeight(_obj:WideString;val:extended);
    procedure setTop(_obj:WideString;val:extended);
    function getWidth(_obj:WideString):extended;
    procedure ConfigurePropsForPrint(AName,ACaption,ADSName:WideString; RowIdx,ColIdx, MaxRowIdx,MaxColIdx: Integer);
  public
    constructor create();
    procedure PreviewReport(_id:integer);
  end;

  T_BezWatku = class(TService)
    ADOConnection1: TADOConnection;
    SaveDialog1: TSaveDialog;
    frxReport1: TfrxReport;
    StringDS: TfrxUserDataSet;
    procedure ServiceStart(Sender: TService; var Started: Boolean);
    procedure ServiceExecute(Sender: TService);
        procedure InsertInFile(info: String = '');
  private
      ADOConnection: TADOConnection;
     ADOQuery2: TADOQuery;
     ADOQuery3: TADOQuery;
     dsHeader: TfrxDBDataset;
     dsDetails: TfrxDBDataset;
     frMy: TfrxReport;
     frCodeBar: TfrxBarCodeObject;
     SaveDialog2: TSaveDialog;
     frxPDFExport1: TfrxPDFExport;
    { Private declarations }


  public
     ADOQuery: TADOQuery;
    report:TReportEngine;
    function GetServiceController: TServiceController; override;

    { Public declarations }
  end;



var
  _BezWatku: T_BezWatku;

implementation

uses UWMSreport,UDMFastReport;

{$R *.DFM}

procedure ServiceController(CtrlCode: DWord); stdcall;
begin
  _BezWatku.Controller(CtrlCode);
end;

function T_BezWatku.GetServiceController: TServiceController;
begin
  Result := ServiceController;
end;


procedure T_BezWatku.InsertInFile(info: String = '');
const
  FileName = 'C:\_Moje_Projekty\Usługa\_PrawdilowaBezWatku\Log.txt';
var
  F : TextFile;
begin
  try
    AssignFile(F, FileName);
    try
      if FileExists(FileName) then
        Append(F)
      else
        Rewrite(F);
        if info <> '' then

         Writeln(F, info, ' ', DiskFree(0))
        else
        Writeln(F, DateTimeToStr(Now), ' ', DiskFree(0));

    finally
      CloseFile(F);
    end;
  except
  end;
end;

procedure TReportEngine.detalAfterScroll(DataSet: TDataSet);
var
  _ds : TDataSet;
  a: string;
  b: Integer;
   frx:TFrxComponent;
begin
  _BezWatku.ADOQuery3.Close;
  _BezWatku.ADOQuery3.SQL.Clear;
  _BezWatku.ADOQuery3.SQL.Add('SELECT DO BAZY');

   _BezWatku.ADOQuery3.Open;
    _BezWatku.ADOQuery3.First;

    if (_BezWatku.ADOQuery3.RecordCount = 0) then
      Self.setVisible('DetailData1', false);

    while not _BezWatku.ADOQuery3.Eof do
    begin
              if _BezWatku.ADOQuery3.FieldByName('Visible').AsInteger = 1 then
          ConfigurePropsForPrint(
            _BezWatku.ADOQuery3.FieldByName('Name').AsWideString,
            _BezWatku.ADOQuery3.FieldByName('Caption').AsWideString,
            'WZDetails',
            _BezWatku.ADOQuery3.FieldByName('RowIdx').AsInteger,
            _BezWatku.ADOQuery3.FieldByName('ColIdx').AsInteger,
            _BezWatku.ADOQuery3.FieldByName('MaxRowIdx').AsInteger,
            _BezWatku.ADOQuery3.FieldByName('MaxColIdx').AsInteger
          );
      _BezWatku.ADOQuery3.Next;
    end;
end;

procedure TReportEngine.PreviewReport(_id:integer);
var
  LFileStream: TFileStream;
begin
  _BezWatku.frMy.PrepareReport();
    LFileStream := TFileStream.Create(_BezWatku.SaveDialog1.FileName + '.pdf', fmCreate or fmShareDenyNone);
       try
        _BezWatku.frxPDFExport1.Stream  := LFileStream;
      _BezWatku.frMy.Export(_BezWatku.frxPDFExport1)
    finally
      FreeAndNil(LFileStream);
      _BezWatku.frxPDFExport1.Stream := NIL;
    end;
end;





procedure TReportEngine.ConfigurePropsForPrint(AName, ACaption, ADSName: WideString; RowIdx,
  ColIdx, MaxRowIdx, MaxColIdx: Integer);
 var
    _lbl : TfrxMemoView;
    _frx : TFrxComponent;
    _lblWidth: extended;
    _lblHeight: extended;
    _BandPropsWidth: extended;
    _topEmptySpace: extended;
  begin
    _lbl:=nil;
    _frx:=_BezWatku.frMy.FindObject(AName);
    if _frx<>nil then
      _lbl:=(_frx as  TfrxMemoView);
    if _lbl=nil then exit;

    _lblWidth := 50 ;
    _lblHeight := 20;
    _BandPropsWidth := self.getWidth('DetailData1')-self.getWidth('Memo31');
    _topEmptySpace := 10;
    _lbl.Text := ACaption+': '+'['+ADSName+'."'+_lbl.datafield+'"]';
    _lbl.Top := (_topEmptySpace + (_lblHeight * RowIdx));
    _lbl.Left := ((_BandPropsWidth / (MaxColIdx+1)) * ColIdx)+10;
    _lbl.width := (_BandPropsWidth / (MaxColIdx+1));

    _lbl.Visible:=true;
    self.setHeight('DetailData1',_topEmptySpace + (_lblHeight * (MaxRowIdx+1)));
    self.setHeight('Memo39',_topEmptySpace + (_lblHeight * (MaxRowIdx+1)));
    self.setHeight('Line5',_topEmptySpace + (_lblHeight * (MaxRowIdx+1)));
    self.setTop('Line1',_topEmptySpace + (_lblHeight * (MaxRowIdx+1)));
end;


constructor TReportEngine.create();
var
  frFile:WideString;
begin
  frFile:='C:\_Moje_Projekty\Usługa\_PrawdilowaBezWatku\rwz.fr3';
  _BezWatku.frMy.LoadFromFile(frFile);
  _BezWatku.frxPDFExport1.filename:=_BezWatku.frMy.ReportOptions.Name;
  _BezWatku.ADOQuery2.AfterScroll:=detalAfterScroll;
end;




 procedure TReportEngine.setVisible(_obj: WideString; param: boolean);
var
  frx:TFrxComponent;
begin
  frx:=_BezWatku.frMy.FindObject(_obj);
  if frx<>nil then
    frx.Visible:=param;
end;

procedure TReportEngine.setHeight(_obj: WideString; val: extended);
var
  frx:TFrxComponent;
begin
  frx:=_BezWatku.frMy.FindObject(_obj);
  if frx<>nil then
    frx.Height:=val;
end;

procedure TReportEngine.setTop(_obj: WideString; val: extended);
var
  frx:TFrxComponent;
begin
  frx:=_BezWatku.frMy.FindObject(_obj);
  if frx<>nil then
    frx.top:=val;
end;

 function TReportEngine.getWidth(_obj: WideString): extended;
var
  frx:TFrxComponent;
begin
  result:=0;
  frx:=_BezWatku.frMy.FindObject(_obj);
  if frx<>nil then
    result:=frx.Width;
end;
procedure T_BezWatku.ServiceStart(Sender: TService; var Started: Boolean);
const
  SQLStr ='SELECT DO BAZY';
    SQLStr2 ='SELECT DO BAZY';
begin
 CoInitialize(nil);
  try
    ADOconnection:=TADOConnection.Create(Nil);
    ADOconnection.ConnectionString :='STRING DO BAZY';
    ADOconnection.LoginPrompt := False;
    ADOQuery:=TADOQuery.Create(Nil);
    ADOQuery.Connection:=ADOConnection;
    fReportdm.ADOConnection1.ConnectionString :='STRING DO BAZY';
    ADOQuery.SQL.Text := SQLStr;


        ADOconnection:=TADOConnection.Create(Nil);
    ADOconnection.ConnectionString :='STRING DO BAZY';
    ADOconnection.LoginPrompt := False;
    ADOQuery:=TADOQuery.Create(Nil);
    ADOQuery.Connection:=ADOConnection;
    ADOQuery.SQL.Text := SQLStr;

    ADOQuery2:=TADOQuery.Create(Nil);
    ADOQuery2.Connection:=ADOConnection;
    ADOQuery2.SQL.Text := SQLStr2;

    ADOQuery3:=TADOQuery.Create(Nil);
    ADOQuery3.Connection:=ADOConnection;

    dsHeader := TfrxDBDataset.Create(nil);
   dsHeader.UserName := 'Header';
   dsHeader.CloseDataSource := False ;
   dsHeader.DataSet := ADOQuery;
   dsHeader. BCDToCurrency := False ;

  dsDetails :=  TfrxDBDataset.Create(NIL);
  dsDetails.UserName := 'Details';
  dsDetails.CloseDataSource := False;
  dsDetails.DataSet := ADOQuery2;
  dsDetails.BCDToCurrency := False;

  frMy := TfrxReport.Create(Nil);
  frMy.Version := '4.13.2';
  frMy.DotMatrixReport := False;
  frMy.IniFile := '\Software\Fast Reports';
  frMy.PreviewOptions.Buttons := [pbPrint, pbLoad, pbSave, pbExport, pbZoom, pbFind, pbOutline, pbPageSetup, pbTools, pbEdit, pbNavigator, pbExportQuick];
  frMy.PreviewOptions.Modal := False;
  frMy.PreviewOptions.Zoom := 1.000000000000000000;
  frMy.PrintOptions.Printer := 'Default';
  frMy.PrintOptions.PrintOnSheet := 0;
  frMy.ReportOptions.CreateDate := 42030.347937847200000000;
  frMy.ReportOptions.Name := 'WWW';
  frMy.ReportOptions.LastChange := 43089.560934537040000000;
  frMy.ScriptLanguage := 'PascalScript';



  frxPDFExport1 := TfrxPDFExport.Create(NIL);
  frxPDFExport1.UseFileCache := True;
  frxPDFExport1.ShowProgress := True;
  frxPDFExport1.OverwritePrompt := False;
  frxPDFExport1.DataOnly := False;
  frxPDFExport1.PrintOptimized := False;
  frxPDFExport1.Outline := False;
  frxPDFExport1.Background := False;
  frxPDFExport1.HTMLTags := True;
  frxPDFExport1.Quality := 95;
  frxPDFExport1.Title := 'WWW';
  frxPDFExport1.Author := 'FastReport';
  frxPDFExport1.Subject := 'FastReport PDF export';
  frxPDFExport1.ProtectionFlags := [ePrint, eModify, eCopy, eAnnot];
  frxPDFExport1.HideToolbar := False;
  frxPDFExport1.HideMenubar := False;
  frxPDFExport1.HideWindowUI := False;
  frxPDFExport1.FitWindow := False;
  frxPDFExport1.CenterWindow := False;
  frxPDFExport1.PrintScaling := False;


  SaveDialog2:= TSaveDialog.Create(NIL);
  SaveDialog2.DefaultExt := '*.PDF';
  SaveDialog2.FileName := 'TEST';
  SaveDialog2.Filter := 'PDF files|*.PDF';
  SaveDialog2.InitialDir := 'C:\_Moje_Projekty\Usługa\_PrawdilowaBezWatku';
             report:=TReportEngine.create();
  except
   on E: Exception do
    _BezWatku.InsertInFile(E.Message);

  end;
end;

procedure T_BezWatku.ServiceExecute(Sender: TService);

begin
  while not Terminated do
  Begin
      try
        ADOConnection1.Connected := True;
        ADOQuery.Active := True;
        ADOQuery.Open;

        report.PreviewReport(1);
      except
       on E: Exception do
        _BezWatku.InsertInFile(E.Message);
      end;

    _BezWatku.InsertInFile;
    ServiceThread.ProcessRequests(False);
    Sleep(100000);
  End;
end;

end.


0

Tu nie chodzi o wyświetlanie z FastReport, ale o wyświetlanie w ogóle. W bardzo dużym uproszczeniu service nie wyświetla na ekranie, który widzisz. Wyświetl sobie jakąś formę czy np ShowMessage. I przeczytaj np to: https://msdn.microsoft.com/en-us/library/windows/desktop/ms683502(v=vs.85).aspx

0

paskudny kod, nie chce mi sie go w calosci analizowac, ale w usludze wystrzegaj sie wyswietlania czegokolwiek, np. masz tam przy eksporcie frxPDFExport1.ShowProgress := True; co pewnie chce pokazac jakis progresbar itp itd.
Nie wiem też co tam robi SaveDialog etc

0

@Sadam2, @lampasss
Generalnie zgoda, usługi nie powinny nić wyrzucać na ekran.
Ale technicznie jest to możliwe, o ile zezwoli się usłudze na interakcję z pulpitem.
Nie mam pewności czy taka interakcja zadziała jeśli usługa działa na koncie "SYSTEM".

0
grzegorz_so napisał(a):

@Sadam2
Generalnie zgoda, usługi nie powinny nić wyrzucać na ekran.

Przecież napisałem "w dużym uproszczeniu". Oczywiście, że z usługi można wyświetlać. Ale pytacz powinien sobie więcej poczytać. To "więcej" też w uproszczeniu :-).

0

@Sadam2 @lampasss @grzegorz_so
Ale ja nie chce wyświetlać raportu.
Ja chcę aby usługa mi go tylko zapisywała do pliku *.PDF.
I tak on działą, lecz nie w usłudze.

0

Nie testowałem tego ale jak Ci się uda to pochwal się na formum bo sam mam gdzieś to na liście "todo" ;)
Gdyby Ci się jednak nie udało to zrób sobie apkę działającą w tray'y i ustaw ją na autostart ;)

0
lukasz_p92 napisał(a):

@Sadam2 @lampasss @grzegorz_so
Ale ja nie chce wyświetlać raportu.

To przeczytaj, co dokładnie robi metoda PreviewReport.
To, co chcesz a to, co robisz, to dwie różne sprawy. I tak, jak Ci pisali - usługa nie może wyświetlać GUI, a PreviewReport chce pokazać gui.

Po prawdzie, można zmusić usługę do wyświetlenia GUI (przynajmniej na Windows 7), ale to nie do końca działa i jest mocno upierdliwe.

0
Juhas napisał(a):
lukasz_p92 napisał(a):

@Sadam2 @lampasss @grzegorz_so
Ale ja nie chce wyświetlać raportu.

To przeczytaj, co dokładnie robi metoda PreviewReport.
To, co chcesz a to, co robisz, to dwie różne sprawy. I tak, jak Ci pisali - usługa nie może wyświetlać GUI, a PreviewReport chce pokazać gui.

Po prawdzie, można zmusić usługę do wyświetlenia GUI (przynajmniej na Windows 7), ale to nie do końca działa i jest mocno upierdliwe.

O czym ty mówisz... o procedurze którą sam napisałem i ją tak nazwałem? Chyba coś Ci się pomyliło z jakąś systemową metodą, bo MOJA procedura PreviewReport tylko buduje raport i go eksportuje jako PDF, bez ŻADNEGO wyświetlania zawartości...

@woolfik
Jak na razie udało mi się uruchamiać usługę i ja zatrzymywać beż żadnego błędu.
Musiałem wyłączyć możliwość używania globalnego Dataset

frMy.EngineOptions.UseGlobalDataSetList := False;

Niestety raport dalej nie jest tworzony. Jeżeli uda mi się wygenerować taki raport, dam znać.

1

Weź jeszcze jedną rzecz pod uwagę ... w przypadku jakiegoś błędu przy generowaniu lub "przygotowywaniu" raportu FR ma swoją własną obsługę błędów (wyskakujące okienka). Niestety w usłudze może to powodować problem i wywalać usługę całkowicie. Jest natomiast któraś metoda (nie pamiętam nazwy), która powoduje "wyciszenie" wyjątków i np zrzut do loga. Weź to pod uwagę przy końcowej wersji ;)

1

Udało się napisać usługę która to realizuje. I jak już wspomniałem, usługa nic nie wyświetlała a tylko tworzyła i zapisywała plik w formacie PDF. ;)

@woolfik
Muszę poprawić kod i podeślę.

Dzięki chłopaki za odzew, zawsze co "dwie" głowy to nie jedna :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1