This document contains several examples of how to use the code in the Environment Variables Unit. They are:
Demo projects that implement these examples are available from the
EnvVarsDemo directory of the DelphiDabbler Doodlings Repository.
This example demonstrates the use of the TPJEnvVars component. The example uses the old EnumNames methods and its callback method in order to enumerate all the environment variable names.
Drop a TPJEnvVars component, a list box, a label, two edit boxes and two buttons on a form. Add the following private methods and event handlers:
procedure TForm1.EnvNamesEnum(const VarName: string; Data: Pointer);
// Private callback method of type TPJEnvVarsEnum adds env var names to
// list box
begin
TStrings(Data).Add(VarName);
end;
procedure TForm1.UpdateList;
// Displays all environment vars in list box
begin
ListBox1.Clear;
PJEnvVars1.EnumNames(EnvNamesEnum, ListBox1.Items);
Label1.Caption := Format('%d environment variables', [PJEnvVars1.Count]);
Edit1.Text := '';
Edit2.Text := '';
end;
procedure TForm1.FormCreate(Sender: TObject);
// Display program's environment vars in list
begin
UpdateList;
end;
procedure TForm1.ListBox1Click(Sender: TObject);
// Display selected env var name and value
begin
Edit1.Text := ListBox1.Items[ListBox1.ItemIndex];
Edit2.Text := PJEnvVars1.Values[Edit1.Text];
end;
procedure TForm1.Button1Click(Sender: TObject);
// Update or create env var named in Edit1 with new value per Edit2 (empty
// string in Edit2 deletes var)
begin
if Edit1.Text <> '' then
begin
PJEnvVars1.Values[Edit1.Text] := Edit2.Text;
UpdateList;
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
// Delete env var named in Edit1
begin
if Edit1.Text <> '' then
begin
PJEnvVars1.DeleteVar(Edit1.Text);
UpdateList;
end;
end;
The program behaves as follows:
Note: This example is similar to Example 2 which accomplishes the same task using the environment variable manipulation routines instead of the component.
This example also demonstrates the use of the TPJEnvVars component, but this time uses the newer TPJEnvVarsEnumerator class to enumerate the environment variable names. This enumerator is created by calling the GetEnumerator method. From Delphi 2005 onwards this enumerator enables the use of the for .. in loop construct. Warning: If GetEnumerator is called directly from code then the caller must free the enumerator instance.
Drop a TPJEnvVars component and a list view on a form. Add two columns named "Name" and "Value" to the list view and set the list view's properties as follows:
alClient
False
True
vsReport
Now an OnCreate event handler for the form as follows:
procedure TForm1.FormCreate(Sender: TObject);
procedure AddListItem(Name: string);
var
LI: TListItem;
begin
LI := ListView1.Items.Add;
LI.Caption := Name;
LI.SubItems.Add(PJEnvVars1.Values[Name]);
end;
var
Name: string;
{$IFNDEF FORINSUPPORTED}
Enum: TPJEnvVarsEnumerator;
{$ENDIF}
begin
{$IFDEF FORINSUPPORTED}
for Name in PJEnvVars1 do
AddListItem(Name);
{$ELSE}
Enum := PJEnvVars1.GetEnumerator;
try
while Enum.MoveNext do
begin
Name := Enum.Current;
AddListItem(Name);
end;
finally
Enum.Free;
end;
{$ENDIF}
end;
This code detects whether for .. in loops are supported using conditional compilation and uses the construct if available. Therefore, add the following compiler directives to the unit before the definition of FormCreate:
{$UNDEF FORINSUPPORTED}
{$IFDEF CONDITIONALEXPRESSIONS}
{$IF CompilerVersion >= 17.0} // >= Delphi 2005
{$DEFINE FORINSUPPORTED}
{$IFEND}
{$ENDIF}
The demo is quite simple. It merely adds the names and values of all the environment variables to the list view on start up. It uses the TPJEnvVarsEnumerator enumerator to get all the environment variable names. Note that any environment variables that have no name are ignored by this enumerator.
This example demonstrates the use of the GetEnvVarValue, SetEnvVarValue, DeleteEnvVar and GetAllEnvVars routines.
Drop a list box, two edit boxes and two buttons on a form and add
PJEnvVars to your uses clause. Now enter the following code:
procedure TForm1.UpdateList;
// Displays all environment vars in list box
var
SL: TStringList;
Idx: Integer;
begin
ListBox1.Clear;
SL := TStringList.Create;
try
GetAllEnvVars(SL);
for Idx := 0 to Pred(SL.Count) do
ListBox1.Items.Add(SL.Names[Idx]);
Edit1.Text := '';
Edit2.Text := '';
finally
SL.Free;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
// Display program's environment vars in list
begin
UpdateList;
end;
procedure TForm1.ListBox1Click(Sender: TObject);
// Display selected env var name and value
begin
Edit1.Text := ListBox1.Items[ListBox1.ItemIndex];
Edit2.Text := GetEnvVarValue(Edit1.Text);
end;
procedure TForm1.Button1Click(Sender: TObject);
// Update or create env var named in Edit1 with new value per Edit2 (empty
// string in Edit2 deletes var)
begin
if Edit1.Text <> '' then
begin
SetEnvVarValue(Edit1.Text, Edit2.Text);
UpdateList;
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
// Delete env var named in Edit1
begin
if Edit1.Text <> '' then
begin
DeleteEnvVar(Edit1.Text);
UpdateList;
end;
end;
The program behaves identically to Example 1a which accomplishes a similar task using the TPJEnvVars component.
This example demonstrates the use of the ExpandEnvVars function.
Drop two memo controls and one button on a form and add
PJEnvVars to your uses clause. Now add the event handlers
listed below:
procedure TForm1.FormCreate(Sender: TObject); begin Memo1.Text := 'This is my temp folder: "%TEMP%"'; end; procedure TForm1.Button1Click(Sender: TObject); begin Memo2.Text := ExpandEnvVars(Memo1.Text); end;
Enter some text, including environment variable references (such as %TEMP%), in the first memo. Clicking the button replaces the environment variable names with their values and displays the expanded string in the second memo.
This example demonstrates the use of the CreateEnvBlock function. It involves creating two programs:
Create a new application with a main form named SlaveForm. Drop
a memo control onto the form, and set its Align property to
alClient and clear the Lines property. Make sure the
PJEnvVars unit is in your uses clause. Give the form the
following OnCreate handler:
procedure TSlaveForm.FormCreate(Sender: TObject); begin GetAllEnvVars(Memo1.Lines); end;
Save the project as SlaveApp and compile. The memo will display
all of SlaveApp's environment variables when the program is
executed.
Create a new application with a main form named MasterForm. Drop
a memo control onto the form and clear its text. Add a button and a check
box below the memo. Ensure the PJEnvVars unit is referenced in
the uses clause. Add the following helper procedure and button event
handler:
procedure ExecProg(const ProgName: string; EnvBlock: Pointer);
// Creates a new process for given program passing any given environment block
var
SI: TStartupInfo;
PI: TProcessInformation;
CreateFlags: DWORD;
SafeProgName: string;
begin
// ensure ProgName has ref count of 1: its memory is writeable
// re issue with CreateProcessW: see http://bit.ly/bTRc7D
SafeProgName := ProgName;
UniqueString(SafeProgName);
// set up for CreateProcess
FillChar(SI, SizeOf(SI), 0);
SI.cb := SizeOf(SI);
// set flags according to if unicode environment block
{$IFDEF UNICODE}
CreateFlags := CREATE_UNICODE_ENVIRONMENT;
{$ELSE}
CreateFlags := 0;
{$ENDIF}
CreateProcess(
nil, PChar(SafeProgName), nil, nil, True,
CreateFlags, EnvBlock, nil, SI, PI
);
end;
procedure TMasterForm.Button1Click(Sender: TObject);
var
EnvBlock: Pointer;
BlockSize: Integer;
begin
// Create the environment block
BlockSize := CreateEnvBlock(Memo1.Lines, CheckBox1.Checked, nil, 0);
// BlockSize is in Characters, not bytes: so needs converting to bytes
GetMem(EnvBlock, BlockSize * SizeOf(Char));
try
CreateEnvBlock(Memo1.Lines, CheckBox1.Checked, EnvBlock, BlockSize);
// Execute the slave app
ExecProg('SlaveApp.exe', EnvBlock);
finally
FreeMem(EnvBlock);
end;
end;
Save the project as MasterApp in the same folder as
SlaveApp and compile.
When MasterApp is run, enter some environment variables in
NAME=VALUE format in the memo control. Place each
NAME=VALUE pair on a different line.
Now click the button. A copy of SlaveApp should run, displaying
just the environment variables you entered.
Return to MasterApp and check the check box. Click the button
again to spawn another instance of SlaveApp. This new instance
will have a copy of MasterApp's environment variables along
with the new ones you entered in MasterApp's memo control.
This example demonstrates the use of both overloaded versions of GetAllEnvVarNames and EnvBlockSize.
Drop three labels, two edit controls, two list boxes, one button and a TPJEnvVars component on a form. Set the following properties:
'Name'.
'Value'.
'Update'.
Create an OnCreate event handler for the form, an OnClick event handler for the button and an OnClick event handler that is attached to both list boxes. Also create a private method of the form class named UpdateListsEtc. Code the methods as follows:
procedure TForm1.UpdateListsEtc;
var
Idx: Integer;
Names: TStringDynArray;
begin
GetAllEnvVarNames(ListBox1.Items);
Names := GetAllEnvVarNames;
ListBox2.Clear;
for Idx := 0 to High(Names) do
ListBox2.Items.Add(Names[Idx]);
Label3.Caption := Format('Environment block size: %d', [EnvBlockSize]);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
UpdateListsEtc;
end;
procedure TForm1.ListBoxClick(Sender: TObject);
begin
Edit1.Text := (Sender as TListBox).Items[(Sender as TListBox).ItemIndex];
Edit2.Text := PJEnvVars1.Values[Edit1.Text];
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
PJEnvVars1.Values[Trim(Edit1.Text)] := Trim(Edit2.Text);
UpdateListsEtc;
end;
If the Types unit is provided in your version of Delphi, add it to the uses clause.
UpdateListsEtc populates the list boxes and displays the environment block size in Label3. ListBox1 is populated with all environment variable names using the TStrings overload of GetAllEnvVarNames while ListBox2 is populated by using GetAllEnvVarNames's string array overload. Both list boxes should contain exactly the same information.
Selecting a name in either list box copies the name into the first edit control and the environment variable's value in the second edit control. Entering a new name or value and clicking the Update button updates the environment variable, repopulates the lists and updates the environment block size.