Link to home
Start Free TrialLog in
Avatar of LeTay
LeTay

asked on

windows gui application started via scheduled task

I developed a Delphi application that has one single main form
If the application is started with one parameter, the application "processes" this parameter and do some work.
The processing is started on the OnActivate event of the form
Now I schedule a task (Windows XP) to start that application with one parameter
It is shedule for 0:30 (midnight)
On that day, I login remotely around 11:00 and see the form of the application on the screen, but nothing is "running" (there is a TMemo which displays the execution activity and it is emplty)
I just click on the form and then ... it starts !
That behavior is different if I run the application myself : the form is "auto" activated, which does not seem to be the case when the scheduler starts it
Is it enough if I "force" the form to be active by coding for example in the OnShow event a Form1.Activate ???
Avatar of Emmanuel PASQUIER
Emmanuel PASQUIER
Flag of France image

I just tested to start an application with a label text changed when the form is activated, from the scheduler at a specific time. I worked normally. So it is not only a pb with the scheduler launching the application, but probably because at the time your application is launch, there is something preventing the activation of the form.
There might be a way to fix this, but maybe you should not rely on the Form.onActivate event.
The onShow event could be tried to do what you intended in the onActivate, but it might have issues as well.
Otherwise, a Timer with interval = 1, that you disable or destroy once the event is executed.
ASKER CERTIFIED SOLUTION
Avatar of 8080_Diver
8080_Diver
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of LeTay
LeTay

ASKER

Hello dear epasquier
I have tried this : in the onShow event, I code Form1.Activate
The OnActivate part I kept unchanged
What the latter does is some initialisation and then, if the application is started with a parameter, it "processes" the parameter
The parameter is in fact a file name that contains some instructions in a script language I created.
I created a special such script which asks the application to issue a dir c: command  , then asks to display a message on the screen (and in a log file), then loop on sleep etc...
Now I made several test
1. I start the application without parameter
I get the form. I ask there (Tedit field) the application to "run" my script.
It works, the loop works forever
2. I  start the application with the parameter
The form is never displayed
The log contains a coupe of iteration of the loop
The executable is still alive, I have to kill it of course

So already that simple test looks strange ?
Why is the form not displayed ???


Avatar of LeTay

ASKER

Hello,
I do not understand precisely the advantage of a Timer
Do you mean that it is necessary so that the Application has finished some startup and the I can launch my processing safely ?
> Why is the form not displayed ???
because you are still in the onShow event, which occurs before the real display of the form. Which is exactly the kind of 'issues' with onShow I was talking about.

About your loop : I don't know exactly what you have, but it sounds not too good :
when you loop on sleep, you should call Application.HandleEvent here and there (or completely replace sleep with HandleEvent) to allow for a minimum of system/GUI events to be handled.
Otherwise, while you stuck your application in an event, nothing will happen.
HandleEvent will make your application going Idle if no events are remaining, which is good for your CPU.

You must stop this loop also if Application.Terminated is set to true. That way, you can close the form, and the application without having to kill it
Avatar of LeTay

ASKER

The loop is just a test
I didn't finally use a sleep
Will try with the Timer...
I generally use the timer approach for precisely the reason you indicated . . . it lets the app's form be shown and then, when the timer function goes off, none of the application's start up processes are involved.  In the code triggered by the timer's event, you can put a call to a function/procedure that does all of the actual processing.  However, you do need to remember to a) disable the timer and b), when your processing finishes, call Application.Terminate to shut your application down automatically.
When I want to limit the time allowed for the process to complete, I set a boolean to indicate that the process has been initiated, then I change the timer's timeout and re-enable it before I call the processing procedure.  The boolean flag for the process having been intiated is checked each time the timer goes of but the second time results in the Application.Terminate call (whether the process is completed or not).  Of course, this means that the processing would ahve to be something that could be interrupted and that it would, in effect, have to update some sort of control persistent mechanism (e.g. a database table with control records for processes) so that the next time the app runs it could pick up from where it left off.
In some cases (e.g. ones where I don't really care how long the processing takes but I do care if nothing is happening for too long), I'll have the app reset the timer periodically, as long as it is actually doing something. ;-)
Using the timer avoids complications such as what you ran into with the loop test you did, i.e. the form didn't actually display.
after the onshow event there is a paint event on the event queue
you need to post a event on that queue, after the paint event

procedure TForm1.OnShow(Sender: TObject);
begin
  PostMessage(Handle, WM_USER, 0, 0);
end;

then catch that message and your sure the window has been painted:

type
  TForm1 = class(TForm)
  // etc
  protected
    procedure WMUser(var Msg: TMessage); message WM_USER;
  end;

procedure TForm1.WMUser(var Msg: TMessage);
begin
  // call your code here
end;