Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Using CreateProcess() in a service

2,057 views
Skip to first unread message

Peter

unread,
May 17, 2007, 1:11:05 PM5/17/07
to
I am creating a service that exec's another app using CreateProcess().

The code builds the command line for the other app, exec's it with
CreateProcess and then waits for a file generated by the other app to be
ready.

When I run the test code via a delphi form as a user it runs fine: the
CreateProcess is executed, the file is built slowly, the dephi part of
my app waits for the file to be complete and the procedure is ended.
This it does as expected.

When I run it as a service the CreateProcess line of code is executed my
app then continues to the wait loop but does not progress. The command
executed by the createprocess only starts to run once the wait loop has
timed out and the service goes idle.

I have tried changing the creation flags from:

CREATE_NEW_PROCESS_GROUP and NORMAL_PRIORITY_CLASS
to
CREATE_NEW_CONSOLE and HIGH_PRIORITY_CLASS

but it makes no difference.


Any ideas?


Peter

Peter

unread,
May 17, 2007, 1:16:28 PM5/17/07
to

Peter Below (TeamB)

unread,
May 17, 2007, 2:28:29 PM5/17/07
to
Peter wrote:

Plenty, but most are not printable <g>. Insufficient data, I'm afraid.
What type of program do you start? Does it have a GUI, a console, none
of the above? Does it access network drives or other net resources?
What is the actual code you use to start it and wait on it?

--
Peter Below (TeamB)
Don't be a vampire (http://slash7.com/pages/vampires),
use the newsgroup archives :
http://www.tamaracka.com/search.htm
http://groups.google.com

Ray Marron

unread,
May 17, 2007, 2:53:38 PM5/17/07
to
"Peter" <in...@accenttechnology.o.uk> wrote in message
news:464c8ca8$1...@newsgroups.borland.com...

>I am creating a service that exec's another app using CreateProcess().
[...]

I do this successfully from a service. The app I launch was written by me,
and is a regular windows app (not a console app) with no window or GUI of
any kind.

Here is the CreateProcess call I use (si is a TStartupInfo,
IConn.WorkerProcess is a TProcessInfo):

FillChar(si, SizeOf(si), #0);
si.cb := SizeOf(si);
si.dwFlags := STARTF_USESHOWWINDOW or STARTF_FORCEOFFFEEDBACK; // No
"busy" cursor!
si.wShowWindow := SW_SHOWNORMAL;
if CreateProcess(nil, zCommand, nil, nil, False,
CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS,
nil, nil, si, IConn.WorkerProcess) then begin

I think Peter Below asked the $64K question: Would the app you're launching
get busted for behavior unbecoming a service? ;)

--
Ray Marron

Peter

unread,
May 17, 2007, 3:29:04 PM5/17/07
to
Peter Below (TeamB) wrote:
> Peter wrote:
>
>> I am creating a service that exec's another app using CreateProcess().
>>
>> The code builds the command line for the other app, exec's it with
>> CreateProcess and then waits for a file generated by the other app to
>> be ready.
>>
>> When I run the test code via a delphi form as a user it runs fine:
>> the CreateProcess is executed, the file is built slowly, the dephi
>> part of my app waits for the file to be complete and the procedure is
>> ended. This it does as expected.
>>
>> When I run it as a service the CreateProcess line of code is executed
>> my app then continues to the wait loop but does not progress. The
>> command executed by the createprocess only starts to run once the
>> wait loop has timed out and the service goes idle.
>>
>> I have tried changing the creation flags from:
>>
>> CREATE_NEW_PROCESS_GROUP and NORMAL_PRIORITY_CLASS
>> to
>> CREATE_NEW_CONSOLE and HIGH_PRIORITY_CLASS
>>
>> but it makes no difference.
>>
>> Any ideas?
>
> Plenty, but most are not printable <g>. Insufficient data, I'm afraid.

> What type of program do you start? Does it have a GUI, a console, none
> of the above?

As you can see from the test code the app is PDFcreator. It has a GUI
but I am using it from the command line. This drives, in my case, Word
and Excel via OLE with output being a PDF with a fixed path and
filename. PDFCreator is suitably configured to run silently.

Does it access network drives or other net resources?

No, it is accessing BLOB's exported from a table to a fixed filename on
a local drive. In this case the file is located in C:\Temp.

> What is the actual code you use to start it and wait on it?

Here is the simple implementation of CreateProcess().

I have tried a couple of waits, both simple and similar to this:

I can just hear the "of course it wont work" but why?

Thanks

Peter

---------------------------------------

S := Format('
"E:\Program Files\PDFCreator\PDFcreator.exe" /NoStart /PF"%s",
[FileName]);

ExecNewProcess(S, False);

TimeOut := 10;
while not FileExists('C:\Temp\DocuStor.PDF) and (Timeout > 0) do
begin
Sleep(1000);
Dec(Timeout);
end;

---------------------------------------

function ExecNewProcess(ProgramName : String; Wait: Boolean): String;
var
StartInfo : TStartupInfo;
ProcInfo : TProcessInformation;
CreateOK : Boolean;
Wd: DWord;
P: Pointer;
begin
Result := '';

FillChar(StartInfo, SizeOf(TStartupInfo), #0);
FillChar(ProcInfo, SizeOf(TProcessInformation), #0);
StartInfo.cb := SizeOf(TStartupInfo);

CreateOK := CreateProcess(nil,
PChar(ProgramName),
nil,
nil,
False,
CREATE_NEW_PROCESS_GROUP+NORMAL_PRIORITY_CLASS,
nil,
nil,
StartInfo,
ProcInfo);


if CreateOK then
begin
if Wait then
WaitForSingleObject(ProcInfo.hProcess, INFINITE);
end
else
begin
Result := Format('Unable to execute: %s ', [ProgramName]);
end;

CloseHandle(ProcInfo.hProcess);
CloseHandle(ProcInfo.hThread);
end;

Remy Lebeau (TeamB)

unread,
May 17, 2007, 4:49:45 PM5/17/07
to

"Peter" <pete...@accenttechnology.co.uk> wrote in message
news:464c...@newsgroups.borland.com...

> As you can see from the test code the app is PDFcreator. It has
> a GUI but I am using it from the command line.

Don't use GUI apps from a service at all. Especially if the GUI app
happens to ever popup a dialog for any reason. Then there would be no
way for the user to interact it with it at all, and no way to dismiss
the dialog, and so the child process will be frozen indefinately.

> Here is the simple implementation of CreateProcess().

You are waiting for the child process to fully exit before then
entering the loop that waits for the file. But you are using an
infinite timeout in that wait, so your service process is going to
freeze up while the child process is frozen. You really should stay
away from infinite timeouts unless you can guarantee that they will
never truely take forever to be signaled. In this case, I would
suggest using a smaller timeout, maybe a minute or so, and then
forcibly kill the child process if it takes too long and report back
to the user or NT log about the timeout error.

You are also not closing either of the thread or process handles for
the child process until after it has fully exited. Since you don't
use the thread handle for anything, you should close it right away.


Gambit


Peter Below (TeamB)

unread,
May 18, 2007, 6:41:18 AM5/18/07
to
Peter wrote:

> > What type of program do you start? Does it have a GUI, a console,
> > none of the above?
> As you can see from the test code the app is PDFcreator. It has a GUI
> but I am using it from the command line. This drives, in my case,
> Word and Excel via OLE with output being a PDF with a fixed path and
> filename. PDFCreator is suitably configured to run silently.

Does that program work by installing a virtual printer driver? That may
be the source of the problem since the service runs under a separate
account (System by default), and printers are a per-account thing. By
default the service account will not have any printers available.

japp

unread,
May 21, 2007, 3:23:51 AM5/21/07
to
If the service is interactive you may be able to launch a GUI console app
the you are doing for session 0. It will fail on Vista and may fail on XP
for console <> 0. The GUI app will run as System Account. You can launch it
as well just doing:
ShellExecute(Handle, 'open', PChar(myApp), nil, nil, SW_SHOWNORMAL);

If the service is not interactive you can launch a GUI app in any account on
the same session with GetProcessWindowStation,
OpenWindowStation,SetProcessWindowStation, OpenDesktop, add ACES to desktop,
CreateProcessAsUser, etc.

If you have to be concerned with sessions then OpenProcessToken,
DuplicateTokenEx, WTSGetActiveConsoleSessionId, SetTokenInformation,
CreateProcessAsUser.

Make a Google search and you will find all details.

In every case you can launch either a GUI or a console.

japp


"Peter" <pete...@accenttechnology.co.uk> wrote in message
news:464c...@newsgroups.borland.com...

japp

unread,
May 21, 2007, 3:28:49 AM5/21/07
to
This is completely wrong.
What could have said is: Take care launching GUI application under the
System account because they have an implicit security risk.

"Remy Lebeau (TeamB)" <no....@no.spam.com> wrote in message
news:464cc01a$1...@newsgroups.borland.com...

Remy Lebeau (TeamB)

unread,
May 21, 2007, 4:25:35 AM5/21/07
to

"japp" <someon...@yahoo.com> wrote in message
news:4651...@newsgroups.borland.com...

> This is completely wrong.
> What could have said is: Take care launching GUI application under
> the System account because they have an implicit security risk.

That statement does not negate what I said earlier. So don't go
saying that what I say is "completely wrong" when it is not wrong at
all.

The use of GUIs from a service, either directly or indirectly, is
highly discouraged and should be avoided at all costs. Displaying a
GUI from a service, especially a non-interactive service, can
potentially lock up the service, as the GUI would be displayed in a
different desktop that the user can't see or do anything with, and
thus cannot respond to or dismiss.

Microsoft disallows interactive services in Vista now because of their
potential security risk. That much is true. But so is what I said
earlier as well. I've written several services over the years. I
know how they work.


Gambit


japp

unread,
May 21, 2007, 1:23:57 PM5/21/07
to
Remy:

You said:
"
Don't use GUI apps from a service at all. Especially if the GUI app
happens to ever popup a dialog for any reason
"

I answered:


"
This is completely wrong.
What could have said is: Take care launching GUI application under
the System account because they have an implicit security risk.
"

Now you say:


"
That statement does not negate what I said earlier.

The use of GUIs from a service, either directly or indirectly, is
highly discouraged and should be avoided at all costs. Displaying a
GUI from a service, especially a non-interactive service, can
potentially lock up the service, as the GUI would be displayed in a
different desktop that the user can't see or do anything with, and
thus cannot respond to or dismiss.
"

But what you say now is not what you said in the first instance, because
launching an app from a service is not the same thing as opening a window to
the user from the service. You can launch an app from a service and are even
encouraged to do so by Microsoft.

You say


"
I've written several services over the years. I
know how they work.
"

It does not appear like you do.

Remy Lebeau (TeamB)

unread,
May 21, 2007, 3:25:14 PM5/21/07
to

"japp" <someon...@yahoo.com> wrote in message
news:4651d5ad$1...@newsgroups.borland.com...

> launching an app from a service is not the same thing as
> opening a window to the user from the service.

Launching a new process in general from a service is fine. But if
that new process then displays its own GUI, or if the service tries to
display its own GUI directly, they can both cause problems if not set
up correctly. I said as much in both earlier messages.

> You can launch an app from a service and are even encouraged
> to do so by Microsoft.

Non-interactive apps can be created within the context of the
service's account just fine. But if the app needs to display a GUI,
then the process has to be created within the context of the logged in
user's interactive account to work properly.


Gambit


0 new messages