rogerson@PEDEV.Columbia.NCR.COM (Dale Rogerson) (09/19/89)
Here is some information on spawining Windows that I have
pulled from the net this year. I do not know who posted
this information. However, several people have stated that these
methods work. Hope they help!!!!
-----Dale
Rogerson-----
=======================================================================
Recently I posted an article asking for help spawning other apps from
within a Windows app. I received a number of mail responses and I tried
out all of the suggestions. Since I've seen others asking the same question
as I did I thought I would present my findings.
1 - spawn? from the standard library will work --- most of the time!
Sometimes it seems to crash in a nasty way.
2 - using DOS function 4B works --- most of the time!
Sometimes it will crash as well, usually with ENOMEM.
3 - the winning suggestion was received from Microsoft, and confirmed by
someone from hDC (sorry I forget your name).
Here goes:
/* reliable Windows spawn code */
GlobalCompact((DWORD)-1); /* compact the global heap */
LockData(0); /* lock down your data segment */
spawnl(P_NOWAIT, "newapp.exe", "newapp", NULL);
UnlockData(0); /* unlock your data segment */
The interesting bits are the GlobalCompact - to give yourself some room,
and the LockData - stop data pointers from becoming orphans.
===========================================================================
>Has anyone out there tried to get one windows task to spawn another task in
>Windows/286? I would like to startup some homemade "device drivers" from my
>application program. I can't find any Window functions for creating another
>Windows process. I am suspicious of spawning since you can't run a Windows
>app from the DOS command line. In other words, I want a system of programs
>to be initiated when the user starts up the main application window.
This came from online, and it works for running other windows apps.
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
# readme.doc
# s.c
# spawh.shar
# spawn
# spawn.c
# spawn.def
# spawn.lnk
# spawn.rc
# wspawn.asm
# This archive created: Tue Dec 6 17:54:54 1988
# By: Charles Anderson (The Midgard Realm, St Paul, MN)
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'readme.doc'
then
echo shar: "will not over-write existing file 'readme.doc'"
else
cat << \SHAR_EOF > 'readme.doc'
To spawn an application in the windows 2.03 system, it is required
that the spawning app. uses the interupt 21 function 4b DOS call
to perform the spawn and that the spawning app. remain resident in
the system until the spawned application finishes.
This sample provides the assembler code, assembled object file,
and a C include file containing the function prototyping. The
C source files included will spawn a copy of the calculator and
then fall into a "getmessage loop". The getmessage loop is removed
from the initialization sources to minimize the amount of memory
needed to keep the spawning application active.
SHAR_EOF
fi
if test -f 's.c'
then
echo shar: "will not over-write existing file 's.c'"
else
cat << \SHAR_EOF > 's.c'
#include "windows.h"
/* small, resident piece of code. In windows 2.03, the spawing
* application must remain resident until the spawned application
* completes. This loop is removed from rest of the application
* code segment so that the memory wasted could be minimized.
*/
int FAR PASCAL Loop()
{
MSG msg;
while (GetMessage ((LPMSG)&msg, NULL, 0, 0))
DispatchMessage ((LPMSG)&msg);
return (int)msg.wParam;
}
SHAR_EOF
fi
if test -f 'spawh.shar'
then
echo shar: "will not over-write existing file 'spawh.shar'"
else
cat << \SHAR_EOF > 'spawh.shar'
SHAR_EOF
fi
if test -f 'spawn'
then
echo shar: "will not over-write existing file 'spawn'"
else
cat << \SHAR_EOF > 'spawn'
spawn.obj: spawn.c
CL -d -c -AS -Gsw -Os -Zped -NT _TEXT spawn.c
s.obj: s.c
CL -d -c -AS -Gsw -Os -Zped -NT _LOOP s.c
wspawn.obj: wspawn.asm
masm wspawn;
spawn.exe: spawn.obj s.obj wspawn.obj spawn.rc spawn.def
link4 @spawn.lnk
mapsym spawn
rc spawn.rc
SHAR_EOF
fi
if test -f 'spawn.c'
then
echo shar: "will not over-write existing file 'spawn.c'"
else
cat << \SHAR_EOF > 'spawn.c'
#include "windows.h"
#include "process.h"
int FAR PASCAL Int21Function4B(BYTE,LPSTR,LPSTR); /* assembler dos interface */
int FAR PASCAL Loop(); /* resident loop */
typedef struct {
WORD environment;
LPSTR commandline;
LPSTR FCB1;
LPSTR FCB2;
} EXECBLOCK; /* as defined in MS-DOS PROG. REF */
EXECBLOCK exec;
WORD w [2];
HANDLE hInst;
int CauseSpawn (app)
LPSTR app;
{
int i;
GlobalCompact (-1L); /* free as much memory as possible */
LockData (0); /* lock data segment */
exec.environment = 0; /* pass default environment */
exec.commandline = (LPSTR)"\0\r"; /* command line to spawned application */
/* the command line has the format:
* byte: number of chars in command line not to include the return char */
/* char[]: command characters */
/* char: return character */
/* example: to send an application the file name foo.txt as the command
* line.
* exec.commandline = (LPSTR)"\007foo.txt\r";
* NOTE: the \007 is octal seven, the number of characters in 'foo.txt'
*/
w[0] = 2; /* two byte command show arg. */
w[1] = SHOW_OPENWINDOW; /* command show arg. */
exec.FCB1 = (LPSTR)w; /* point to the command show */
exec.FCB2 = (LPSTR)NULL; /* reserved */
i = Int21Function4B (0, (LPSTR)app, (LPSTR)&exec); /* call assembler function */
UnlockData (0); /* unlock the data segment */
return (i);
}
int PASCAL WinMain (hInstance, hPrevInstance, lpszCmdLine, cmdShow)
HANDLE hInstance, hPrevInstance;
LPSTR lpszCmdLine;
int cmdShow;
{
hInst = hInstance;
CauseSpawn ((LPSTR)"calc.exe"); /* spawn calculator */
if (hPrevInstance)
return (TRUE); /* if a previous instance of this
* sample exists, exit. */
return (Loop ()); /* if first instance, remain resident */
}
SHAR_EOF
fi
if test -f 'spawn.def'
then
echo shar: "will not over-write existing file 'spawn.def'"
else
cat << \SHAR_EOF > 'spawn.def'
NAME SPAWN
DESCRIPTION 'Simple Microsoft Windows Application'
STUB 'WINSTUB.EXE'
CODE MOVEABLE DISCARDABLE
DATA MOVEABLE MULTIPLE
SEGMENTS
_TEXT MOVEABLE DISCARDABLE
_LOOP MOVEABLE DISCARDABLE
STACKSIZE 4096
HEAPSIZE 128
SHAR_EOF
fi
if test -f 'spawn.lnk'
then
echo shar: "will not over-write existing file 'spawn.lnk'"
else
cat << \SHAR_EOF > 'spawn.lnk'
spawn s wspawn
/align:16
spawn/map/li
slibw
spawn.def
SHAR_EOF
fi
if test -f 'spawn.rc'
then
echo shar: "will not over-write existing file 'spawn.rc'"
else
cat << \SHAR_EOF > 'spawn.rc'
#include "style.h"
SHAR_EOF
fi
if test -f 'wspawn.asm'
then
echo shar: "will not over-write existing file 'wspawn.asm'"
else
cat << \SHAR_EOF > 'wspawn.asm'
include cmacros.inc
sBegin CODE
assumes CS,CODE
cProc Int21Function4B,<PUBLIC,FAR>,<bx,cx,dx,si,di,es,ds>
parmB mode ; mode of int 21 func. 4b call
parmD path ; address of exe file name
parmD execblock ; address of exec block
cBegin
mov al,mode ; set register args as per int 21
lds dx,path ; function 4b DOS Programmers Reference
les bx,execblock
mov ah,4bh
int 21h ; call DOS
cEnd
sEnd CODE
END
SHAR_EOF
fi
exit 0
# End of shell archive
--roper@cs.washington.edu (Michael Roper) (09/20/89)
Dale Rogerson writes: > 3 - the winning suggestion was received from Microsoft, and confirmed by > someone from hDC (sorry I forget your name). > > /* reliable Windows spawn code */ > spawnl(P_NOWAIT, "newapp.exe", "newapp", NULL); We don't use spawnl() at hDC. The shar included with the above post contains the code that should be used and is the same code Microsoft provides through Online. Michael Roper hDC Computer Corp.