This is a new site that's currently running on alpha code. There are going to be bugs. If you discover any, please report them on the site's issues page (GitHub account required). Thanks.
Warning: Many URLs are going to change. Refer to the README file to discover which library project's documentation has been completed.
Applies to: ~>3.0
This appendix contains some example code that can be used to create [inheritable handles] to files and pipes.
If you don’t want to get involved with all this low level stuff you can just use TPJPipe and TPJFileHandle from the I/O Utility Classes to open pipes and files respectively with inheritable handles.
Pipes have two handles: a write handle used to write data into the pipe and a read handle to read data out of the other end. Here’s a little routine to open an un-named pipe of a given size with inheritable handles. If the size is given as 0
then a pipe with default size is created.
procedure CreatePipe(out ReadHandle, WriteHandle: THandle; const Size: LongWord = 0);
var
Security: TSecurityAttributes; // file's security attributes
begin
// Set up security structure so file handle is inheritable
Security.nLength := SizeOf(Security);
Security.lpSecurityDescriptor := nil;
Security.bInheritHandle := True;
if not Windows.CreatePipe(ReadHandle, WriteHandle, @Security, Size) then
raise Exception.CreateFmt(
'Can_t create pipe: "%s"', [SysErrorMessage(GetLastError)]
);
end;
Files have a single handle. Whether the handle is used for reading or writing the file (or both) depends on how it was opened.
Two routines are presented. The first opens an existing file for reading while the second creates a new empty file for writing. There are other possibilities of course, such as opening an existing file for appending, which are not covered here. However the implementations are very similar.
This example could be used to get a handle suitable for use in redirecting a console application’s standard input to a file. You would assign the handle to TPJConsoleApp’s StdIn property.
function OpenInputFile(const FileName: string): THandle;
var
Security: TSecurityAttributes; // file's security attributes
begin
// Set up security structure so file handle is inheritable (NT)
Security.nLength := SizeOf(Security);
Security.lpSecurityDescriptor := nil;
Security.bInheritHandle := True;
// Open the file for reading
Result := CreateFile(
PChar(FileName), // file name
GENERIC_READ, // readable file
FILE_SHARE_READ, // share read access
@Security, // security attributes (NT only)
OPEN_EXISTING, // file must exist
FILE_ATTRIBUTE_NORMAL, // just the normal attributes
0 // no template file (NT only)
);
if Result = INVALID_HANDLE_VALUE then
raise Exception.CreateFmt('Can_t open file "%s"', [FileName]);
end;
If you want to redirect a console application standard output or standard error to a file, this routine provides a suitable handle for assignment to TPJConsoleApp’s StdOut or StdErr properties.
function CreateOutputFile(const FileName: string): THandle;
var
Security: TSecurityAttributes; // file's security attributes
begin
// Set up security structure so file handle is inheritable (NT)
Security.nLength := SizeOf(Security);
Security.lpSecurityDescriptor := nil;
Security.bInheritHandle := True;
// Create new empty file
Result := CreateFile(
PChar(FileName), // file name
GENERIC_WRITE, // writeable file
0, // no sharing
@Security, // security attributes (NT only)
CREATE_ALWAYS, // always create the file, even if exists
FILE_ATTRIBUTE_NORMAL, // just the normal attributes
0 // no template file (NT only)
);
if Result = INVALID_HANDLE_VALUE then
raise Exception.CreateFmt('Can_t create file "%s"', [FileName]);
end;
To open a file for appending, or to create it if it doesn’t exist, replace CREATE_ALWAYS
above with OPEN_ALWAYS
.