Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

weird event log while freeing a TMemoryStream

Status
Not open for further replies.

Griffyn

Programmer
Jul 11, 2002
1,077
0
36
AU
Hi all,

This has me stumped. I have a service application that is adding to the system Event Log (seen via eventvwr.exe) with the relevent part that reads: "Dataset not in edit or insert mode."

It's occuring seemingly as a result of freeing a TMemoryStream object that was used to retrieve a blob field from an Access database, so there is some sort of sanity about it - I just can't figure exactly what that is.

Some code:

Code:
[navy][i]// for automatic syntax highlighting see faq102-6487 
[/i][/navy][b]function[/b] TDocPrint.ProcessTransactions: Boolean;

  [b]procedure[/b] _ReplaceDestination(AStream: TMemoryStream);
  [b]var[/b]
    sl : TStringList;
    c : Integer;
  [b]begin[/b]
    sl := TStringList.Create;
    [b]try[/b]
      sl.LoadFromStream(AStream);
      [b]for[/b] c := [purple]0[/purple] [b]to[/b] sl.Count - [purple]1[/purple] [b]do[/b]
      [b]begin[/b]
        [b]if[/b] SameText(LeftStr(sl[c], [purple]11[/purple]), [teal]'  Printer ='[/teal]) [b]then[/b]
          sl[c] := Format([teal]'  Printer = '[/teal][teal]'%s'[/teal][teal]''[/teal], [qry.FieldByName([teal]'Printer'[/teal]).AsString]);
        [b]if[/b] SameText(LeftStr(sl[c], [purple]9[/purple]), [teal]'  Email ='[/teal]) [b]then[/b]
          sl[c] := Format([teal]'  Email = '[/teal][teal]'%s'[/teal][teal]''[/teal], [qry.FieldByName([teal]'Email'[/teal]).AsString]);
      [b]end[/b];
      AStream.Clear;
      sl.SaveToStream(AStream);
    [b]finally[/b]
      sl.Free;
    [b]end[/b];
  [b]end[/b];

[b]var[/b]
  qry : TADOQuery;
  m : TMemoryStream;
  p : String;
[b]begin[/b]
  Result := False;
  p := ExtractFilePath(ParamStr([purple]0[/purple]));
  qry := CreateDBQuery([teal]'SELECT * FROM Queue '[/teal]
    + [teal]'WHERE (Printed is Null) AND (NextRetry<=Now()) '[/teal]
    + [teal]'ORDER BY ID'[/teal]);
  [b]try[/b]
    [b]try[/b]
      qry.Open;
      qry.First;
      Result := [b]not[/b] qry.EOF;
      [b]if[/b] Result [b]then[/b]
      [b]begin[/b]
        [navy][i]// ... snip ...
[/i][/navy]        m := TMemoryStream(qry.CreateBlobStream(qry.FieldByName([teal]'Blob'[/teal]), bmRead));
        [b]try[/b]
          _ReplaceDestination(m);    [navy][i]// pretty sure this is not causing any issues[/i][/navy]
          m.SaveToFile(p + [teal]'printing.txt'[/teal]);
          LogMessage([teal]'trap 1'[/teal]);
        [b]finally[/b]
          m.Free;            [navy][i]// this line must be causing the event
[/i][/navy]        [b]end[/b];
        LogMessage([teal]'trap 2'[/teal]);
      [b]end[/b];
      [navy][i]// ... snip ...
[/i][/navy]    [b]except[/b]
      [b]on[/b] E: Exception [b]do[/b]
        LogErr([teal]'ProcessTransactions'[/teal], E);   [navy][i]// logs to database
[/i][/navy]    [b]end[/b];
  [b]finally[/b]
    qry.Free;
  [b]end[/b];
[b]end[/b];

The two LogMessage lines there I've used to trap the offending message - it appears in the Event Log between these two trap logs.

One other weird thing is that in the Event Log, my two trap logs have a Source of 'DocPrint' (which is the value of the TService.Name property), while the offending log message has a Source of 'DocPrintSvc.exe', which is the filename of the service.

The purpose of the code block is to save the contents of a database blob field to a text file. The _ReplaceDestination procedure changes a couple of entries in the TMemoryStream (it contains text strings only).

I'm not sure what else I can say - any clues anyone?
 
if the m.free line would case an exception, the 2nd logmessage would never be executed.

one question:

this is a service application, are you using a separate thread or do you use the onExecute handler of the main serviceapp framework?

to make sure that I understand your problem well:

the error/exception you are having is :

"Dataset not in edit or insert mode."

right?


/Daddy

-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
It's a service application. I use a TTimer in the main service thread that fires every second to call this method.

My ServiceExecute method contains only
Code:
[b]while[/b] [b]not[/b] Terminated [b]do[/b]
  ServiceThread.ProcessRequests(True);

There's no exception being thrown here, which is why it's stumping me. I've concluded that the m.Free line is logging this 'error' to the system Event Log, because I've surrounded this line with two trap log lines, and they show up in sequence in the system Event Log:

trap 1
Dataset not in insert or edit mode
trap 2

 
just to be sure:

you are using a TTimer, so your OnTimer event is structured like this? :

Code:
procedure TServiceApp.TimerTimer(Sender : TObject);

begin
 Timer.enabled := false;
 // do work
 Timer.enabled := true;
end;


/Daddy

-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
No, I don't disable the timer within the OnTimer event. My understanding was that OnTimer is a single threaded component, so that it won't fire until the main service thread is idle.

I tested it with the disable..enable within OnTimer - no difference.
 
No, I don't disable the timer within the OnTimer event. My understanding was that OnTimer is a single threaded component, so that it won't fire until the main service thread is idle.

you would be surprised :)

anyway, I can only give some general advice here:

I develop a LOT of service applications for a living.
I always use the same method when developing a service application:

- before making the service I develop a normal windows application and an additional thread. the main business logic is called from the additional thread.

this allows me to fully test/debug the business logic (I also write unit tests for the various components of the BI)

- when everything works, I create the service application:

onStart method spawns my business logic thread
oStop method kills the thread
onExecute method processes the service request

that's about it.
So if I end up in your situation, I just open up my form app and debug/step through the code until I find the problem...

/Daddy

-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
solved - but not sure why this works.

Code:
[b]var[/b]
  qry : TADOQuery;
  m : TMemoryStream;
  s : TStream;
[b]begin[/b]
  [navy][i]// snip
[/i][/navy]  m := TMemoryStream.Create;
  s := qry.CreateBlobStream(qry.FieldByName([teal]'Blob'[/teal]), bmRead);
  [b]try[/b]
    m.CopyFrom(s, [purple]0[/purple]);
    _ReplaceDestination(m);
    m.SaveToFile(p + [teal]'printing.txt'[/teal]);
  [b]finally[/b]
    m.Free;
    s.Free;
  [b]end[/b];
  [navy][i]// snip
[/i][/navy][b]end[/b];

I welcome anyone's thoughts on what's happening here, or not happening here compared to the previous code.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top