Rcm
asked on
Redirecting output when using exec command in Pascal
I'm using a graphical interface in Pascal and I don't want the childprocesses to return ANYTHING back to screen
(so both 1 and 2 (error) should be redirected to nul or to a file when I specify > in my command-string)
Please help me and help me quickly ... This needs to be operational Wednesday 20th June.
Function ShellCommand(Command : String) : Integer;
Var
Redirect : Boolean;
OutputTo : String;
Param : String;
Begin
Redirect := (Pos('>', Command) <> 0);
If Redirect Then
OutputTo := ''
Else
OutputTo := ' 1>nul';
Param := Copy(Command, Pos(' ', Command) + 1, Length(Command) - Pos(' ', Command));
Delete(Command, Pos(' ', Command), Length(Command) - Pos(' ', Command) + 1);
SwapVectors;
Exec(Command, param + OutputTo);
SwapVectors;
ShellCommand := DosExitCode;
End;
(so both 1 and 2 (error) should be redirected to nul or to a file when I specify > in my command-string)
Please help me and help me quickly ... This needs to be operational Wednesday 20th June.
Function ShellCommand(Command : String) : Integer;
Var
Redirect : Boolean;
OutputTo : String;
Param : String;
Begin
Redirect := (Pos('>', Command) <> 0);
If Redirect Then
OutputTo := ''
Else
OutputTo := ' 1>nul';
Param := Copy(Command, Pos(' ', Command) + 1, Length(Command) - Pos(' ', Command));
Delete(Command, Pos(' ', Command), Length(Command) - Pos(' ', Command) + 1);
SwapVectors;
Exec(Command, param + OutputTo);
SwapVectors;
ShellCommand := DosExitCode;
End;
Q: How do I execute an MS-DOS command from within a TP program?
A: The best way to answer this question is to give an example.
{$M 2048, 0, 0} (* <-- Important *)
program outside;
uses dos;
begin
write ('Directory call from within TP by Timo Salmi');
SwapVectors;
Exec (GetEnv('comspec'), '/c dir *.*'); (* Execution *)
SwapVectors;
(* Testing for errors is recommended *)
if DosError <> 0 then
writeln ('Dos error number from ' + GetEnv('comspec'), DosError)
else
writeln ('Mission accomplished, exit code ', DosExitCode);
(* For DosError and DosExitCode details see the TP manual *)
end.
Alternatively, take a look at execdemo.pas from demos.arc which
should be on the disk accompanying Turbo Pascal.
What the above Exec does is that it executes the command
processor (in fact, a new copy of the command processor.) The /c
specifies that the command interpreter is to perform the command,
and then close (not halt). Note that the command (in the example dir
*.*) can be an MS-DOS command, a program, or a batch file.
Note that the DosError and DosExitCode are returned by the first
program in the Exec call, i.e. the command interpreter in the above
example, not by the item in the latter part.
Somewhat surprisingly some users have had difficulties with
redirecting shelled output. It is straight-forward. In the above
code one would use, for example
Exec (GetEnv('comspec'), '/c dir *.* > tmp');
Calling a batch file from within a TP program via the command
interpreter is no different from calling an executable program via
it. Thus, you could use any of the examples below
Exec (GetEnv('comspec'), '/c ' + 'mybatch.bat');
Exec (GetEnv('comspec'), '/c ' + 'myprog.exe par1 par2 par3');
Exec (GetEnv('comspec'), '/c ' + 'myprog2.com par');
Exec (GetEnv('comspec'), '/c ' + 'dir *.*');
Exec (GetEnv('comspec'), '/c type myfile.txt | more');
The extensions .bat, .exe and .com can be, and usually are omitted.
They are given here only for the clarity of the examples.
What the above examples do is that they issue the commands via
the command interpreter. An executable program (but not a batch,
since it must be executed via the command interpreter) can also be
called directly:
Exec ('c:\progdir\myprog.exe', 'par1 par2 par3');
For an example see item #75. A tip from Pedt Scragg: "When calling
the program directly, as in this example, then the extension .exe or
.com needs to be present."
A2: I have also seen it asked how one can swap the Turbo Pascal
program to the disk when shelling. It is unnecessary to program that
separately because there is an excellent program to do that for you.
It is ftp://garbo.uwasa.fi/pc/sysutil/shrom24b.zip. Also of interest
to advanced programmers even if in C
A: The best way to answer this question is to give an example.
{$M 2048, 0, 0} (* <-- Important *)
program outside;
uses dos;
begin
write ('Directory call from within TP by Timo Salmi');
SwapVectors;
Exec (GetEnv('comspec'), '/c dir *.*'); (* Execution *)
SwapVectors;
(* Testing for errors is recommended *)
if DosError <> 0 then
writeln ('Dos error number from ' + GetEnv('comspec'), DosError)
else
writeln ('Mission accomplished, exit code ', DosExitCode);
(* For DosError and DosExitCode details see the TP manual *)
end.
Alternatively, take a look at execdemo.pas from demos.arc which
should be on the disk accompanying Turbo Pascal.
What the above Exec does is that it executes the command
processor (in fact, a new copy of the command processor.) The /c
specifies that the command interpreter is to perform the command,
and then close (not halt). Note that the command (in the example dir
*.*) can be an MS-DOS command, a program, or a batch file.
Note that the DosError and DosExitCode are returned by the first
program in the Exec call, i.e. the command interpreter in the above
example, not by the item in the latter part.
Somewhat surprisingly some users have had difficulties with
redirecting shelled output. It is straight-forward. In the above
code one would use, for example
Exec (GetEnv('comspec'), '/c dir *.* > tmp');
Calling a batch file from within a TP program via the command
interpreter is no different from calling an executable program via
it. Thus, you could use any of the examples below
Exec (GetEnv('comspec'), '/c ' + 'mybatch.bat');
Exec (GetEnv('comspec'), '/c ' + 'myprog.exe par1 par2 par3');
Exec (GetEnv('comspec'), '/c ' + 'myprog2.com par');
Exec (GetEnv('comspec'), '/c ' + 'dir *.*');
Exec (GetEnv('comspec'), '/c type myfile.txt | more');
The extensions .bat, .exe and .com can be, and usually are omitted.
They are given here only for the clarity of the examples.
What the above examples do is that they issue the commands via
the command interpreter. An executable program (but not a batch,
since it must be executed via the command interpreter) can also be
called directly:
Exec ('c:\progdir\myprog.exe', 'par1 par2 par3');
For an example see item #75. A tip from Pedt Scragg: "When calling
the program directly, as in this example, then the extension .exe or
.com needs to be present."
A2: I have also seen it asked how one can swap the Turbo Pascal
program to the disk when shelling. It is unnecessary to program that
separately because there is an excellent program to do that for you.
It is ftp://garbo.uwasa.fi/pc/sysutil/shrom24b.zip. Also of interest
to advanced programmers even if in C
ASKER
To dbrunton:
I don't know if you noticed I removed the GetEnv('ComSpec') and call the program directly ... I did this ON PURPOSE ... because, like you explain ... the dosexitcode and doserror will only be the ones of the program that were executed (and command.com will handle all exceptions itself and by this will return doserror 0 and dosexitcode 0) I really need those codes of the programs that are executed and not the codes of command.com. (always 0). Now ... the redirection works fine when using command.com, but they don't when I call these programs directly. My question was how I could prevent these programs to return anything to screen (because I have a graphical interface and when these programs have output, my graphical interface is all messed up.)
ps. I use {$M 12288, 0, 40000}
I can't lower these values by much anymore ... I'm using an internal copy command (blockread and write), PCX-files, a huge list of variables, ... and I also do a getImage and putImage (when I use a "pop-up"-window) ...
I just don't want ANY output from the exec-command to mess-up my graphical interface. And I need the errorlevels and doserrors to check if the command was successfull (wich I cannot check when using exec(getenv('comspec'), ' /c ' + command);
I don't know if you noticed I removed the GetEnv('ComSpec') and call the program directly ... I did this ON PURPOSE ... because, like you explain ... the dosexitcode and doserror will only be the ones of the program that were executed (and command.com will handle all exceptions itself and by this will return doserror 0 and dosexitcode 0) I really need those codes of the programs that are executed and not the codes of command.com. (always 0). Now ... the redirection works fine when using command.com, but they don't when I call these programs directly. My question was how I could prevent these programs to return anything to screen (because I have a graphical interface and when these programs have output, my graphical interface is all messed up.)
ps. I use {$M 12288, 0, 40000}
I can't lower these values by much anymore ... I'm using an internal copy command (blockread and write), PCX-files, a huge list of variables, ... and I also do a getImage and putImage (when I use a "pop-up"-window) ...
I just don't want ANY output from the exec-command to mess-up my graphical interface. And I need the errorlevels and doserrors to check if the command was successfull (wich I cannot check when using exec(getenv('comspec'), ' /c ' + command);
ASKER
Oh, btw ... the output of some programs need to be in a file ... wich I then can read so I can print it with the OutTextXY command or use it as a variable (like I have a program to read the serial number of a dell and compaq-computer ... the number normally will be reported to screen, but I redirect it to a file and then read it and use the number as parameter to some other commands)
OK
Here are some possible solutions. There are about 9 small little code samples from the SWAG archive here and in the next postings to do with redirection and exec.
Unit dualout;
{ This Unit is designed to demonstrate directing all screen output to a File }
{ in addition to the normal display. This means that any Write or Writeln }
{ will display normally on the screen and also be Recorded in a Text File. }
{ The File name For the output can be supplied by a command line parameter }
{ in the Format - dual=c:\test\output.dat or you can provide an environment }
{ Variable named dual that supplies the File name or it will default to the }
{ current directory and output.dat. }
Interface
Uses
globals, { contains the Function exist, which tests For the existence of }
{ a File. It also defines the Type str80 as String[80] }
Dos,
tpString; { from TPro. Needed For StUpCase Function in Procedure initialise}
Const
DualOn : Boolean = False;
DualOK : Boolean = False;
fname : str80 = 'output.dat'; { The default File name For the output }
Type
DriverFunc = Function(Var f: TextRec): Integer;
Var
OldExitProc : Pointer; { For saving old Exit Procedure }
OldInOutOutput, { The old output InOut Function }
OldFlushOutput : DriverFunc; { The old output Flush Function }
dualf : Text;
Procedure dual(status: Boolean);
{========================= ========== ========== ========== ========== ========== }
Implementation
Var
cmdline : String;
Procedure DualWrite(Var f: TextRec);
{ Writes the output from stdout to a File }
Var
x : Word;
begin
For x := 0 to pred(f.BufPos) do
Write(dualf, f.BufPtr^[x]);
end; { DualWrite }
{$F+}
Function InOutOutput(Var f: TextRec): Integer;
begin
DualWrite(f); { Write to the File }
InOutOutput := OldInOutOutput(f); { Call the old Function }
end; { InOutOutput }
Function FlushOutput(Var f: TextRec): Integer;
begin
DualWrite(f); { Write to the File }
FlushOutput := OldFlushOutput(f); { Call the old Function }
end; { FlushOutput }
Procedure DualExitProc;
begin
close(dualf);
ExitProc := OldExitProc; { Restore the old Exit Procedure }
With TextRec(output) do begin
InOutFunc := @OldInOutOutput; { Restore the old output Record }
FlushFunc := @OldFlushOutput; { Restore the old flush Record }
end; { With }
end; { DualExitProc }
{$F-,I-}
Procedure dual(status: Boolean);
Var
ErrorCode : Integer;
begin
if status then begin
assign(dualf,fname);
if Exist(fname) then { open For writing }
append(dualf)
else { start new File }
reWrite(dualf);
ErrorCode := Ioresult;
if ErrorCode <> 0 then
halt(ErrorCode);
With TextRec(output) do begin
{ This is where the old output Functions are rerouted }
OldInOutOutput := DriverFunc(InOutFunc);
OldFlushOutput := DriverFunc(FlushFunc);
InOutFunc := @InOutOutput;
FlushFunc := @FlushOutput;
end; { With }
OldExitProc := ExitProc; { Save the current Exit Procedure }
ExitProc := @DualExitProc; { Install new Exit Procedure }
DualOn := True;
end { if status }
else { switch dual output off } begin
if DualOn then begin
close(dualf); if Ioresult = 0 then; { dummy call }
ExitProc := OldExitProc; { Restore the old Exit Procedure }
OldExitProc := nil;
With TextRec(output) do begin
InOutFunc := @OldInOutOutput; { Restore the old output Record }
FlushFunc := @OldFlushOutput; { Restore the old flush Record }
end; { With }
end; { if DualOn }
end; { else }
end; { dual }
{$I+}
Procedure Initialise;
{ Determines if a File name For the output has been provided. }
begin
if GetEnv('DUAL') <> '' then
fname := GetEnv('DUAL')
else begin
if ParamCount <> 0 then begin
cmdline := String(ptr(PrefixSeg,$80)^ );
cmdline := StUpCase(cmdline);
if pos('DUAL=',cmdline) <> 0 then begin
fname := copy(cmdline,pos('DUAL=',c mdline)+5, 80);
if pos(' ',fname) <> 0 then
fname := copy(fname,1,pos(' ',fname)-1);
end; { if pos('Dual... }
end; { if ParamCount... }
end; { else }
end; { Initialise }
begin
Initialise;
end.
*********
{
MARK LEWIS
>> Still need a bit of help here. I can't redirect output from a
>> Program when executing it from a Pascal Program! Is there any
>> this from Pascal? Any help would be greatly appreciated.
> if I understand you, you are using the Exec Procedure to run a
> Program. if that is the Case you won't be ablr to redirect since
> this is a Function of Dos and not the Program you exec. You will
> need to run the Program through a child process in order to
> perform the redirect, something like:
> Exec(GetEnv('COMSPEC'),'/C MyProg.exe>redirect');
one could also utilize duplicate File handles -=B-)
}
Unit Execute;
Interface
Procedure Exec(Path, CmdLine : String);
Implementation
Uses
Dos;
Function ExtractFileName(Var Line : String; Index : Integer) : String;
Var
Temp : String;
begin
Delete(Line, Index, 1);
While (Index <= Length(Line)) and (Line[Index] = ' ') Do
Delete(Line, Index, 1);
Temp := '';
While (Index <= Length(Line)) and (Line[Index] <> ' ') Do
begin
Temp := Temp + Line[Index];
Delete(Line, Index, 1);
end;
ExtractFileName := Temp;
end;
Procedure CloseHandle(Handle : Word);
Var
Regs : Registers;
begin
With Regs Do
begin
AH := $3E;
BX := Handle;
MsDos(Regs);
end;
end;
Procedure Duplicate(SourceHandle : Word;Var TargetHandle : Word);
Var
Regs : Registers;
begin
With Regs Do
begin
AH := $45;
BX := SourceHandle;
MsDos(Regs);
TargetHandle := AX;
end;
end;
Procedure ForceDuplicate(SourceHandl e : Word;Var TargetHandle : Word);
Var
Regs : Registers;
begin
With Regs Do
begin
AH := $46;
BX := SourceHandle;
CX := TargetHandle;
MsDos(Regs);
TargetHandle := AX;
end;
end;
Procedure Exec(Path,CmdLine : String);
Var
StdIn,
Stdout : Word;
Index : Integer;
FName : String[80];
InFile,
OutFile : Text;
InHandle,
OutHandle : Word;
{ ===============>>>> } { change below For STDERR }
begin
StdIn := 0;
StdOut := 1; { change to 2 For StdErr }
Duplicate(StdIn, InHandle); { duplicate standard input }
Duplicate(StdOut, OutHandle); { duplicate standard output }
Index := Pos('>', CmdLine);
if Index > 0 Then { check For output redirection }
begin
FName := ExtractFileName(CmdLine, Index); { get output File name }
Assign(OutFile, FName); { open a Text File }
ReWrite(OutFile); { .. For output }
ForceDuplicate(TextRec(Out File).Hand le, StdOut);{ make output same }
end;
Index := Pos('<', CmdLine);
if Index > 0 Then { check For input redirection }
begin
FName := ExtractFileName(CmdLine, Index); { get input File name }
Assign(InFile, FName); { open a Text File }
Reset(InFile); { For input }
ForceDuplicate(TextRec(InF ile).Handl e, StdIn); { make input same }
end;
Dos.Exec(Path, CmdLine); { run EXEC }
ForceDuplicate(InHandle, StdIn); { put standard input back to keyboard }
ForceDuplicate(OutHandle, StdOut); { put standard output back to screen }
CloseHandle(InHandle); { close the redirected input File }
CloseHandle(OutHandle); { close the redirected output File }
end;
end.
{========================= ========== ========== ========== ========}
{
Use it exactly as you would the normal EXEC Procedure:
Exec('MAsm.EXE','mystuff.A sm');
To activate redirection simply add the redirection symbols, etc:
Exec('MAsm.EXE','mystuff.A sm >err.lst');
One note of caution. This routine temporarily Uses extra handles. It's
either two or four more. The Various books I have are not clear as to
whether duplicated handles 'count' or not. My guess is yes. if you don't
plan on redirecting STDIN then remove all the code For duplicating it to
cut your handle overhead in half.
}
Here are some possible solutions. There are about 9 small little code samples from the SWAG archive here and in the next postings to do with redirection and exec.
Unit dualout;
{ This Unit is designed to demonstrate directing all screen output to a File }
{ in addition to the normal display. This means that any Write or Writeln }
{ will display normally on the screen and also be Recorded in a Text File. }
{ The File name For the output can be supplied by a command line parameter }
{ in the Format - dual=c:\test\output.dat or you can provide an environment }
{ Variable named dual that supplies the File name or it will default to the }
{ current directory and output.dat. }
Interface
Uses
globals, { contains the Function exist, which tests For the existence of }
{ a File. It also defines the Type str80 as String[80] }
Dos,
tpString; { from TPro. Needed For StUpCase Function in Procedure initialise}
Const
DualOn : Boolean = False;
DualOK : Boolean = False;
fname : str80 = 'output.dat'; { The default File name For the output }
Type
DriverFunc = Function(Var f: TextRec): Integer;
Var
OldExitProc : Pointer; { For saving old Exit Procedure }
OldInOutOutput, { The old output InOut Function }
OldFlushOutput : DriverFunc; { The old output Flush Function }
dualf : Text;
Procedure dual(status: Boolean);
{=========================
Implementation
Var
cmdline : String;
Procedure DualWrite(Var f: TextRec);
{ Writes the output from stdout to a File }
Var
x : Word;
begin
For x := 0 to pred(f.BufPos) do
Write(dualf, f.BufPtr^[x]);
end; { DualWrite }
{$F+}
Function InOutOutput(Var f: TextRec): Integer;
begin
DualWrite(f); { Write to the File }
InOutOutput := OldInOutOutput(f); { Call the old Function }
end; { InOutOutput }
Function FlushOutput(Var f: TextRec): Integer;
begin
DualWrite(f); { Write to the File }
FlushOutput := OldFlushOutput(f); { Call the old Function }
end; { FlushOutput }
Procedure DualExitProc;
begin
close(dualf);
ExitProc := OldExitProc; { Restore the old Exit Procedure }
With TextRec(output) do begin
InOutFunc := @OldInOutOutput; { Restore the old output Record }
FlushFunc := @OldFlushOutput; { Restore the old flush Record }
end; { With }
end; { DualExitProc }
{$F-,I-}
Procedure dual(status: Boolean);
Var
ErrorCode : Integer;
begin
if status then begin
assign(dualf,fname);
if Exist(fname) then { open For writing }
append(dualf)
else { start new File }
reWrite(dualf);
ErrorCode := Ioresult;
if ErrorCode <> 0 then
halt(ErrorCode);
With TextRec(output) do begin
{ This is where the old output Functions are rerouted }
OldInOutOutput := DriverFunc(InOutFunc);
OldFlushOutput := DriverFunc(FlushFunc);
InOutFunc := @InOutOutput;
FlushFunc := @FlushOutput;
end; { With }
OldExitProc := ExitProc; { Save the current Exit Procedure }
ExitProc := @DualExitProc; { Install new Exit Procedure }
DualOn := True;
end { if status }
else { switch dual output off } begin
if DualOn then begin
close(dualf); if Ioresult = 0 then; { dummy call }
ExitProc := OldExitProc; { Restore the old Exit Procedure }
OldExitProc := nil;
With TextRec(output) do begin
InOutFunc := @OldInOutOutput; { Restore the old output Record }
FlushFunc := @OldFlushOutput; { Restore the old flush Record }
end; { With }
end; { if DualOn }
end; { else }
end; { dual }
{$I+}
Procedure Initialise;
{ Determines if a File name For the output has been provided. }
begin
if GetEnv('DUAL') <> '' then
fname := GetEnv('DUAL')
else begin
if ParamCount <> 0 then begin
cmdline := String(ptr(PrefixSeg,$80)^
cmdline := StUpCase(cmdline);
if pos('DUAL=',cmdline) <> 0 then begin
fname := copy(cmdline,pos('DUAL=',c
if pos(' ',fname) <> 0 then
fname := copy(fname,1,pos(' ',fname)-1);
end; { if pos('Dual... }
end; { if ParamCount... }
end; { else }
end; { Initialise }
begin
Initialise;
end.
*********
{
MARK LEWIS
>> Still need a bit of help here. I can't redirect output from a
>> Program when executing it from a Pascal Program! Is there any
>> this from Pascal? Any help would be greatly appreciated.
> if I understand you, you are using the Exec Procedure to run a
> Program. if that is the Case you won't be ablr to redirect since
> this is a Function of Dos and not the Program you exec. You will
> need to run the Program through a child process in order to
> perform the redirect, something like:
> Exec(GetEnv('COMSPEC'),'/C
one could also utilize duplicate File handles -=B-)
}
Unit Execute;
Interface
Procedure Exec(Path, CmdLine : String);
Implementation
Uses
Dos;
Function ExtractFileName(Var Line : String; Index : Integer) : String;
Var
Temp : String;
begin
Delete(Line, Index, 1);
While (Index <= Length(Line)) and (Line[Index] = ' ') Do
Delete(Line, Index, 1);
Temp := '';
While (Index <= Length(Line)) and (Line[Index] <> ' ') Do
begin
Temp := Temp + Line[Index];
Delete(Line, Index, 1);
end;
ExtractFileName := Temp;
end;
Procedure CloseHandle(Handle : Word);
Var
Regs : Registers;
begin
With Regs Do
begin
AH := $3E;
BX := Handle;
MsDos(Regs);
end;
end;
Procedure Duplicate(SourceHandle : Word;Var TargetHandle : Word);
Var
Regs : Registers;
begin
With Regs Do
begin
AH := $45;
BX := SourceHandle;
MsDos(Regs);
TargetHandle := AX;
end;
end;
Procedure ForceDuplicate(SourceHandl
Var
Regs : Registers;
begin
With Regs Do
begin
AH := $46;
BX := SourceHandle;
CX := TargetHandle;
MsDos(Regs);
TargetHandle := AX;
end;
end;
Procedure Exec(Path,CmdLine : String);
Var
StdIn,
Stdout : Word;
Index : Integer;
FName : String[80];
InFile,
OutFile : Text;
InHandle,
OutHandle : Word;
{ ===============>>>> } { change below For STDERR }
begin
StdIn := 0;
StdOut := 1; { change to 2 For StdErr }
Duplicate(StdIn, InHandle); { duplicate standard input }
Duplicate(StdOut, OutHandle); { duplicate standard output }
Index := Pos('>', CmdLine);
if Index > 0 Then { check For output redirection }
begin
FName := ExtractFileName(CmdLine, Index); { get output File name }
Assign(OutFile, FName); { open a Text File }
ReWrite(OutFile); { .. For output }
ForceDuplicate(TextRec(Out
end;
Index := Pos('<', CmdLine);
if Index > 0 Then { check For input redirection }
begin
FName := ExtractFileName(CmdLine, Index); { get input File name }
Assign(InFile, FName); { open a Text File }
Reset(InFile); { For input }
ForceDuplicate(TextRec(InF
end;
Dos.Exec(Path, CmdLine); { run EXEC }
ForceDuplicate(InHandle, StdIn); { put standard input back to keyboard }
ForceDuplicate(OutHandle, StdOut); { put standard output back to screen }
CloseHandle(InHandle); { close the redirected input File }
CloseHandle(OutHandle); { close the redirected output File }
end;
end.
{=========================
{
Use it exactly as you would the normal EXEC Procedure:
Exec('MAsm.EXE','mystuff.A
To activate redirection simply add the redirection symbols, etc:
Exec('MAsm.EXE','mystuff.A
One note of caution. This routine temporarily Uses extra handles. It's
either two or four more. The Various books I have are not clear as to
whether duplicated handles 'count' or not. My guess is yes. if you don't
plan on redirecting STDIN then remove all the code For duplicating it to
cut your handle overhead in half.
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Apologies here. I've gone and done a very rough grab from the SWAG archive and grabbed what looked useful. They discuss some of the problems you may have and various solutions.
I didn't have time to sort it out for usefulness. I have broken it into sections by the use of
**********
to show where the breaks are.
You will find the solutions look like they use handles for redirections. Note they don't cover the use of graphics windows. You may have to shoot back to a text based window for some of these solutions to work and then recall your graphic window afterwards.
I didn't have time to sort it out for usefulness. I have broken it into sections by the use of
**********
to show where the breaks are.
You will find the solutions look like they use handles for redirections. Note they don't cover the use of graphics windows. You may have to shoot back to a text based window for some of these solutions to work and then recall your graphic window afterwards.
ASKER
It is working, but now I have troubles with my memory again. It seems like when I try to include one functionality, I loose another.
I'm unable to load the network at this time.
And I can't lower the heap anymore neither the stack.
Aaaargh ... I'm really growing a deep sense of hatered towards dos programming.
I'm unable to load the network at this time.
And I can't lower the heap anymore neither the stack.
Aaaargh ... I'm really growing a deep sense of hatered towards dos programming.
ASKER
I had to do some digging into the code myself, but the help was verry usefull.
ASKER