Call DOS-Interrupts and COMMAMD.COM without loading
Question
Does anyone know hou to call a DOS interrupt or executing DOS COMMAND.COM commands without loading it?
Answer
A:
To execute a DOS interrupt try something like this:
function Test: boolean;
var nRes : integer;
begin
asm
mov AX, 0C000h
int 2Fh
mov nRes, AX
end;
Test := nRes = 0
end;
The code shown below executes the int 2Fh (the multiplexer interrupt) moving
the value C000h in the AX register and testing the result moving the AX
value in the nRes variable.
To execute a command form Delphi try something like this:
var CmdStr :PStr;
begin
CmdStr := 'C:\COMMAND.COM';
if WinExec(CmdStr,SW_SHOWNORMAL) < 32 then
MessageDlg('Could not execute '+StrPas(CmdStr)+'.',mtError,[mbOk],0);
end;
LASTDRIVE Value
Question
Does anyone know how to access the LASTDRIVE value from
CONFIG.SYS from within Delphi? I don't mean parsing the
CONFIG.SYS file, I actually want to get the variable from
the system.
Answer
program CrtApp;
uses WinCrt, winprocs;
function getlastdrive : byte; assembler;
asm
mov ah, $19
call dos3call
mov dl, al
mov ah, $e
call dos3call
end;
begin
Writeln(getlastdrive);
end.
The return value of GetLastDrive is the greatest of 5, the value of
LASTDRIVE= in Config.Sys or tha actual number of drives in the system.
With Novell the number is fixed at 32.
A:
There's a way to do it using Int21 of DOS.
The function 0Eh, Set Default Drive, returns the number of logical
drives.
A short func to do this could be:
Function GetNoOfDrives: Integer; Assembler;
asm
Mov ah,$19; { Get Default drive, used below }
Call Dos3Call;
Mov dl,al; { Set default drive to default drive.. }
Mov ah,$0E; { Set Default Drive }
Call Dos3Call;
Xor ah,ah;
end;
Environment Calls in Delphi
Question
I am looking for a way to read the operating system (DOS) environment
variables(i.e. Path, Prompt, etc.).
Answer
This is code I adapted from someone else's posted code. You pass it the
name of the variable you want to get (eg. PATH) and it returns the value or
'' if it doesn't exist.
function GetDOSEnvVar (const VarName: string): string;
var
Len: integer;
PDOSEnv: PChar;
begin
result := '';
Len := Length(VarName);
PDOSEnv := GetDosEnvironment;
while PDOSEnv^ <> #0 do begin
if (StrLIComp(PDOSEnv, @VarName[1], Len) = 0) and
(PDOSEnv[Len] = '=')
then begin
result := StrPas(PDOSEnv + Len + 1);
break;
end;
Inc(PDOSEnv, StrLen(PDOSEnv) + 1);
end;
end;
A:
This is not necessarily true, for Delphi 1. In one of the subdirectories
beneath Delphi, there is a file named WINDOS.PAS. Compile this unit and use
the GetEnvVar function in that just as you would with Turbo Pascal 7.0.
This is the text taken from that unit. It shows how to use the Windows
GetDosEnvironment call also.
function GetEnvVar(VarName: PChar): PChar;
var
L: Word;
P: PChar;
begin
L := StrLen(VarName);
{$IFDEF Windows}
P := GetDosEnvironment;
{$ELSE}
P := Ptr(Word(Ptr(PrefixSeg, $2C)^), 0);
{$ENDIF}
while P^ <> #0 do
begin
if (StrLIComp(P, VarName, L) = 0) and (P[L] = '=') then
begin
GetEnvVar := P + L + 1;
Exit;
end;
Inc(P, StrLen(P) + 1);
end;
GetEnvVar := nil;
end;
If I remember correctly, correct usage is something like
Var
EnvVariable : Array[0..60] of char;
BEGIN
EnvVariable := GetEnvVar('USER');
END;
Environment variables
Question
How do you change an environment variable from within Delphi? I
would like to set a session environment variable, one which is set
only for the lifetime of the application and is eliminated at
application termination.
Answer
First, do you mean an "environment variable" vis-a-vis Windows, or DOS? I
am presuming you mean Windows environment. Why you are doing this is not
clear, but I will also presume it's because you have two applications
running one of which wants something from the other, and you don't want to
rely on Messaging, DDE, OLE or some other mechanism....
At least, that is the case for me.
Two API functions will serve you:
SetEnvironment and GetEnvironment.
Both are used in the context of GDI functions and were presumably built for
purposes of working with printer drivers, but it turns out they can easily
be twisted to the above needs as well:
Neither of them are well documented in the online windows API help, but both
are poorly mentioned in the Windows programming reference....
Essentially they take the same parameter list:
SetEnvironment(PChar,PChar,Integer)
GetEnvironment(PChar,PChar,Integer)
Use SetEnvironment to place an arbitrary "key" into the environment. Much
like a key value in the DOS environment or INI file - MYKEY=SOMEVALUE would
be written as:
SetEnvironment('MYKEY','SOMEVALUE',Length('SOMEVALUE'));
GetEnvironment retrieves the value associated with the Key, but you need to
know the length of the value before you retrieve it. So, you can first call
GetEnvironment with a Null in the value parameter position and it returns
the length:
BufLen := GetEnvironment('MYKEY',NULL,SOMELARGENUMBER);
MyBuffer := StrAlloc(BufLen +1);
GetEnvironment('MYKEY',MyBuffer,BufLen+1);
SOMELARGENUMBER is used above because (at least in my early trials, I think,
and here is where I would need to go back and check it) when I used 0 there,
GetEnvironment always returned 0. SOMELARGENUMBER (something larger than
your largest anticipated value) for sure will allow the first call to return
a proper length.
BTW, I did notice that when I used SOMELARGENUMBER, GetEnvironment always
returned at least 32, even when my value was only 8...perhaps someone with
even more experience with these functions can explain why... It seems to
work beautifully for my purposes...