mirror of
https://bitbucket.org/Dennis07/lina-components.git
synced 2025-02-02 10:25:22 +02:00
62559dcad1
Signed-off-by: Dennis07 <den.goehlert@t-online.de>
870 lines
23 KiB
ObjectPascal
870 lines
23 KiB
ObjectPascal
unit uFileTools;
|
|
|
|
//////////////////////////////////////
|
|
/// Lina File Tools Unit ///
|
|
/// **************************** ///
|
|
/// (c) 2014 Dennis Göhlert a.o. ///
|
|
//////////////////////////////////////
|
|
|
|
{$IFNDEF MSWINDOWS}
|
|
{$MESSAGE ERROR 'The "uFileTools" unit is only available under MS-Windows OS'}
|
|
{$ENDIF}
|
|
|
|
interface
|
|
|
|
uses
|
|
{ Standard-Units }
|
|
Classes, SysUtils, ShellAPI, Forms, Windows, Math,
|
|
{$IFNDEF NO_GENERIC}
|
|
Generics.Collections,
|
|
{$ENDIF}
|
|
{ Andere Package-Units }
|
|
uBase, uSysTools;
|
|
|
|
type
|
|
{ Fehlermeldungen }
|
|
EDriveNoExist = class(Exception);
|
|
EFileNoExist = class(Exception);
|
|
EMissingTypeDesc = class(Exception);
|
|
EMissingExts = class(Exception);
|
|
EInvalidStyle = class(Exception);
|
|
ENoGetFileOwner = class(Exception);
|
|
|
|
type
|
|
{ Hilfsklassen }
|
|
TFileExecuteMode = (feOpen,feEdit,feExplore,feFind,fePrint);
|
|
TFileNameStyles = set of (fnDirectory,fnExtension);
|
|
TFileAttributes = set of (faReadOnly,faHidden,faSystem,faArchive,faTemporary);
|
|
TInvalidFileName = String[4];
|
|
TInvalidFileNames = array[1..22] of TInvalidFileName;
|
|
|
|
type
|
|
{ Hauptklassen }
|
|
TWinFileInfo = class
|
|
private
|
|
{ Private-Deklarationen }
|
|
FFileName: String;
|
|
public
|
|
{ Public-Deklarationen }
|
|
constructor Create(AFileName: String);
|
|
destructor Destroy; override;
|
|
property FileName: String read FFileName;
|
|
{ function GetSignature: String;
|
|
function GetVersionStructure: Integer;
|
|
function GetVersionFileMS: Integer;
|
|
function GetVersionFileLS: Integer;
|
|
function GetVersionProductMS: Integer;
|
|
function GetVersionProductLS: Integer; }
|
|
end;
|
|
|
|
TWinDrive = class
|
|
private
|
|
{ Private-Deklarationen }
|
|
FDriveChar: Char;
|
|
public
|
|
{ Public-Deklarationen }
|
|
constructor Create(ADriveChar: Char);
|
|
destructor Destroy; override;
|
|
property DriveChar: Char read FDriveChar;
|
|
function GetSpaceTotal: Int64;
|
|
function GetSpaceFree: Int64;
|
|
end;
|
|
|
|
TWinFile = class
|
|
private
|
|
{ Private-Deklarationen }
|
|
FFileName: String;
|
|
FExecuteMode: TFileExecuteMode;
|
|
FDrive: TWinDrive;
|
|
FInfo: TWinFileInfo;
|
|
public
|
|
{ Public-Deklarationen }
|
|
constructor Create(AFileName: String);
|
|
destructor Destroy; override;
|
|
property FileName: String read FFileName;
|
|
property ExecuteMode: TFileExecuteMode read FExecuteMode write FExecuteMode;
|
|
property Drive: TWinDrive read FDrive write FDrive;
|
|
property Info: TWinFileInfo read FInfo write FInfo;
|
|
function GetExtension(WithDot: Boolean = True): String; //ExtractFileExt()
|
|
function GetPath: String; //ExtractFilePath()
|
|
function GetDir: String; //ExtractFileDir()
|
|
function GetFileName(WithExt: Boolean = True): String; //ExtractFileName()
|
|
function GetFolderName: String; //ExtractFileFolder()
|
|
function GetSize: Int64; //GetFileSize()
|
|
//function GetVersion: Extended;
|
|
function GetAttributes: TFileAttributes; //GetFileAttributes();
|
|
function GetOwner: String;
|
|
function GetModified: TDateTime; //GetFileModified()
|
|
function GetCreated: TDateTime; //GetFileCreated()
|
|
function GetAccessed: TDateTime; //GetFileAccessed()
|
|
function Execute: Boolean; //ExecuteFile()
|
|
function SafeExecute: Boolean; //.............
|
|
end;
|
|
|
|
TWinFileArray = array of TWinFile;
|
|
|
|
{$IFNDEF NOGENERIC}
|
|
TWinFileList = TList<TWinFile>;
|
|
{$ENDIF}
|
|
|
|
procedure InitializeInvalidNames;
|
|
function ValidFileName(const FileName: TInvalidFileName; const InvalidFileNames: TInvalidFileNames): Boolean;
|
|
function ValidFileNameStr(const FileName: ShortString; const InvalidFileNames: TInvalidFileNames): Boolean;
|
|
function StrIsPath(const S: String): Boolean;
|
|
function FEModeToPChar(FEMode: TFileExecuteMode): PChar;
|
|
procedure EnsureDirDelimeter(var Dir: String);
|
|
function ExecuteFile(FileName: String; ExecMode: TFileExecuteMode = feOpen;
|
|
InDir: Boolean = False): Boolean;
|
|
function ExtractFileFolder(FileName: String): String;
|
|
procedure ListFiles(Dir: String; var OutList: TStrings; FileExts: array of String;
|
|
NameStyles: TFileNameStyles = []; RecMode: Boolean = False);
|
|
procedure ListFolders(Dir: String; var OutList: TStrings;
|
|
NameStyles: TFileNameStyles = []; RecMode: Boolean = False);
|
|
function ExtractDriveChar(const FileName: String): Char;
|
|
function DriveCharToFileDir(DriveChar: Char): ShortString;
|
|
function DriveCharToFilePath(DriveChar: Char): ShortString;
|
|
function DriveByteToDriveChar(DriveByte: Byte): Char;
|
|
function DriveCharToDriveByte(DriveChar: Char): Byte;
|
|
function DriveExists(DriveByte: Byte): Boolean;
|
|
function GetDriveTypeChar(DriveByte: Byte): UINT;
|
|
function FileTimeToDateTime(FileTime: TFileTime): TDateTime;
|
|
function ConvertFileSize(const InputSize: Int64; ConvertFactor: ShortInt = -1): Extended;
|
|
function GetFileSize(FileName: String): Int64;
|
|
function GetFileModified(FileName: String): TDateTime;
|
|
function GetFileCreated(FileName: String): TDateTime;
|
|
function GetFileAccessed(FileName: String): TDateTime;
|
|
function GetFileAttributes(FileName: String): TFileAttributes;
|
|
|
|
const
|
|
PathDelims = [PathDelim,'/'];
|
|
MAX_PATH_DS = MAX_PATH - 1; //Max. Länge von Dateiname ohne #0-Terminal
|
|
{ Ungültige Dateinamen-Zeichen }
|
|
InvalidFilePathChars = ['*','?','"','<','>','|'];
|
|
InvalidFileNameChars = InvalidFilePathChars + ['\','/',':'];
|
|
{ Umrechnungs-Faktoren }
|
|
TB_TO_B = 4;
|
|
GB_TO_B = 3;
|
|
TB_TO_KB = 3;
|
|
MB_TO_B = 2;
|
|
GB_TO_KB = 2;
|
|
TB_TO_MB = 2;
|
|
KB_TO_B = 1;
|
|
MB_TO_KB = 1;
|
|
GB_TO_MB = 1;
|
|
TB_TO_GB = 1;
|
|
B_TO_KB = -1;
|
|
KB_TO_MB = -1;
|
|
MB_TO_GB = -1;
|
|
GB_TO_TB = -1;
|
|
B_TO_MB = -2;
|
|
KB_TO_GB = -2;
|
|
MB_TO_TB = -2;
|
|
B_TO_GB = -3;
|
|
KB_TO_TB = -3;
|
|
B_TO_TB = -4;
|
|
{ Dateierweiterungen für ListFiles() }
|
|
FXT_ANY = '*.*';
|
|
FXT_EXE = '*.exe';
|
|
FXT_TXT = '*.txt';
|
|
{ Vielleicht später mal implementieren...
|
|
FXT_IMG = ('*.jpg','*.jpeg','*.png','*.tif','*.tiff','*.bmp','*.gif');
|
|
FXT_PAS = ('*.pas','*.dpr','*.dpk','*.dfm');
|
|
FXT_MSO = ('*.doc','*.xls','*.ppt');
|
|
FXT_MSI = ('*.msi');
|
|
FXT_IMG = ('*.img','*.iso'); }
|
|
|
|
var
|
|
InvalidFileNames: TInvalidFileNames;
|
|
|
|
implementation
|
|
|
|
procedure InitializeInvalidNames;
|
|
begin
|
|
InvalidFileNames[01] := 'CON';
|
|
InvalidFileNames[02] := 'PRN';
|
|
InvalidFileNames[03] := 'AUX';
|
|
InvalidFileNames[04] := 'NUL';
|
|
{ COM... }
|
|
InvalidFileNames[05] := 'COM1';
|
|
InvalidFileNames[06] := 'COM2';
|
|
InvalidFileNames[07] := 'COM3';
|
|
InvalidFileNames[08] := 'COM4';
|
|
InvalidFileNames[09] := 'COM5';
|
|
InvalidFileNames[10] := 'COM6';
|
|
InvalidFileNames[11] := 'COM7';
|
|
InvalidFileNames[12] := 'COM8';
|
|
InvalidFileNames[13] := 'COM9';
|
|
{ LPT... }
|
|
InvalidFileNames[14] := 'LPT1';
|
|
InvalidFileNames[15] := 'LPT2';
|
|
InvalidFileNames[16] := 'LPT3';
|
|
InvalidFileNames[17] := 'LPT4';
|
|
InvalidFileNames[18] := 'LPT5';
|
|
InvalidFileNames[19] := 'LPT6';
|
|
InvalidFileNames[20] := 'LPT7';
|
|
InvalidFileNames[21] := 'LPT8';
|
|
InvalidFileNames[22] := 'LPT9';
|
|
end;
|
|
|
|
function ValidFileName(const FileName: TInvalidFileName;
|
|
const InvalidFileNames: TInvalidFileNames): Boolean;
|
|
var
|
|
Index: 1..22;
|
|
begin
|
|
InitializeInvalidNames;
|
|
Result := True;
|
|
for Index := Low(InvalidFileNames) to High(InvalidFileNames) do
|
|
begin
|
|
if InvalidFileNames[Index] = FileName then
|
|
begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function ValidFileNameStr(const FileName: ShortString;
|
|
const InvalidFileNames: TInvalidFileNames): Boolean;
|
|
var
|
|
Index: 1..4;
|
|
TmpIFN: TInvalidFileName;
|
|
begin
|
|
Result := True;
|
|
if Length(FileName) > 4 then
|
|
begin
|
|
Exit;
|
|
end;
|
|
for Index := 1 to 4 do
|
|
begin
|
|
TmpIFN := TmpIFN + FileName[Index];
|
|
end;
|
|
Result := ValidFileName(TmpIFN,InvalidFileNames);
|
|
end;
|
|
|
|
function StrIsPath(const S: String): Boolean;
|
|
{ Prüft, ob ein Dateipfad unter Windows-Systemen gültig ist.
|
|
An dieser stelle sei gesagt: Der Rückgabewert dieser Funktion ist lediglich
|
|
ein Anhaltspunkt und keine Garantie!
|
|
Außerdem wird nicht geprüft, ob die Datei existiert. }
|
|
var
|
|
Index: 1..MAX_PATH_DS; //Integer[1..259]
|
|
SLength: SmallInt;
|
|
NoPathDelim: Boolean;
|
|
NeedPathDelim: Boolean;
|
|
FileName: ShortString;
|
|
begin
|
|
Result := True;
|
|
SLength := Length(S);
|
|
if SLength = 0 then
|
|
begin
|
|
Exit;
|
|
end;
|
|
if SLength > MAX_PATH_DS then
|
|
begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
{ Prüfen, ob Dateiname ungültig ist }
|
|
FileName := '';
|
|
for Index := SLength downto 1 do
|
|
begin
|
|
if S[Index] in PathDelims then
|
|
begin
|
|
Break;
|
|
end else
|
|
begin
|
|
FileName := S[Index] + FileName;
|
|
end;
|
|
end;
|
|
if ValidFileNameStr(FileName,InvalidFileNames) = False then
|
|
begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
{ Parse... }
|
|
NoPathDelim := True;
|
|
NeedPathDelim := False;
|
|
for Index := 1 to SLength do
|
|
begin
|
|
{ -> Doppel-Slash verhindern }
|
|
if NoPathDelim = True then
|
|
begin
|
|
if S[Index] in PathDelims then
|
|
begin
|
|
Result := False;
|
|
Exit;
|
|
end else
|
|
begin
|
|
NoPathDelim := False;
|
|
end;
|
|
end else
|
|
begin
|
|
NoPathDelim := (S[Index] in PathDelims);
|
|
end;
|
|
{ -> Drive-Char validieren }
|
|
if (NeedPathDelim = True) then
|
|
begin
|
|
if S[Index] in PathDelims then
|
|
begin
|
|
NeedPathDelim := False;
|
|
end else
|
|
begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
end;
|
|
if S[Index] = DriveDelim then
|
|
begin
|
|
if Index = 2 then
|
|
begin
|
|
NeedPathDelim := True;
|
|
end else
|
|
begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
end;
|
|
{ -> Auf ungültige Zeichen prüfen }
|
|
if S[Index] in InvalidFilePathChars then
|
|
begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
//For
|
|
end;
|
|
end;
|
|
|
|
function FEModeToPChar(FEMode: TFileExecuteMode): PChar;
|
|
begin
|
|
case FEMode of
|
|
feOpen: Result := 'open';
|
|
feEdit: Result := 'edit';
|
|
feExplore: Result := 'explore';
|
|
feFind: Result := 'find';
|
|
fePrint: Result := 'print';
|
|
else Result := nil;
|
|
end;
|
|
end;
|
|
|
|
procedure EnsureDirDelimeter(var Dir: String);
|
|
begin
|
|
if (Dir[Length(Dir)] <> '\') and (Dir[Length(Dir)] <> '/') then
|
|
begin
|
|
Dir := Dir + '\';
|
|
end else
|
|
begin
|
|
while Length(Dir) >= 1 do
|
|
begin
|
|
if (Dir[Length(Dir) - 1] = '\') or (Dir[Length(Dir) - 1] = '/') then
|
|
begin
|
|
Delete(Dir,Length(Dir) - 1,1);
|
|
end else
|
|
begin
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure ListFiles(Dir: String; var OutList: TStrings; FileExts: array of String;
|
|
NameStyles: TFileNameStyles = []; RecMode: Boolean = False);
|
|
var
|
|
SRec: TSearchRec;
|
|
ExtIndex: Integer;
|
|
begin
|
|
EnsureDirDelimeter(Dir);
|
|
if Length(FileExts) < 1 then
|
|
begin
|
|
raise EMissingExts.Create('Missing file extensions');
|
|
end;
|
|
for ExtIndex := Low(FileExts) to High(FileExts) do
|
|
begin
|
|
if FindFirst(Dir + '*.*',faAnyFile,SRec) = 0 then
|
|
begin
|
|
repeat
|
|
if (SRec.Name <> '.') and (SRec.Name <> '..') then
|
|
begin
|
|
if ((SRec.Attr and faDirectory) = faDirectory) then
|
|
begin
|
|
if RecMode = True then
|
|
begin
|
|
ListFiles(Dir + SRec.Name,OutList,FileExts,NameStyles,RecMode);
|
|
end;
|
|
end else
|
|
begin
|
|
if ((ChangeFileExt(SRec.Name,ExtractFileExt(FileExts[ExtIndex])) = SRec.Name) or
|
|
(ExtractFileExt(FileExts[ExtIndex]) = '.*')) then
|
|
begin
|
|
OutList.Add(SRec.Name);
|
|
if fnDirectory in NameStyles then
|
|
begin
|
|
OutList.Strings[OutList.Count - 1] := Dir + OutList.Strings[OutList.Count - 1];
|
|
end;
|
|
if not (fnExtension in NameStyles) then
|
|
begin
|
|
OutList.Strings[OutList.Count - 1] := ChangeFileExt(OutList.Strings[OutList.Count - 1],'');
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
until FindNext(SRec) <> 0;
|
|
SysUtils.FindClose(SRec);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure ListFolders(Dir: String; var OutList: TStrings;
|
|
NameStyles: TFileNameStyles = []; RecMode: Boolean = False);
|
|
var
|
|
SRec: TSearchRec;
|
|
begin
|
|
EnsureDirDelimeter(Dir);
|
|
if FindFirst(Dir + '*.*',faAnyFile,SRec) = 0 then
|
|
begin
|
|
repeat
|
|
if ((SRec.Attr and faDirectory) = faDirectory) and
|
|
(SRec.Name <> '.') and (SRec.Name <> '..') then
|
|
begin
|
|
if fnDirectory in NameStyles then
|
|
begin
|
|
OutList.Add(Dir + SRec.Name);
|
|
end else
|
|
begin
|
|
OutList.Add(SRec.Name);
|
|
if RecMode = True then
|
|
begin
|
|
ListFolders(Dir + SRec.Name,OutList,NameStyles,RecMode);
|
|
end;
|
|
end;
|
|
end;
|
|
until FindNext(SRec) <> 0;
|
|
SysUtils.FindClose(SRec);
|
|
end;
|
|
if fnExtension in NameStyles then
|
|
begin
|
|
raise EInvalidStyle.Create('The extension file name style is invalid for directory names and has been ignored');
|
|
end;
|
|
end;
|
|
|
|
function ExecuteFile(FileName: String; ExecMode: TFileExecuteMode = feOpen;
|
|
InDir: Boolean = False): Boolean;
|
|
begin
|
|
Result := True;
|
|
try
|
|
if InDir = True then
|
|
begin
|
|
ShellExecute(Application.Handle,FEModeToPChar(ExecMode),PChar(FileName),nil,PChar(ExtractFileDir(FileName)),SW_NORMAL);
|
|
end else
|
|
begin
|
|
ShellExecute(Application.Handle,FEModeToPChar(ExecMode),PChar(FileName),nil,nil,SW_NORMAL);
|
|
end;
|
|
except
|
|
Result := False;
|
|
end;
|
|
end;
|
|
|
|
function ExtractFileFolder(FileName: String): String;
|
|
begin
|
|
Result := ExtractFileName(ExtractFileDir(FileName)); //Name d. übergeord. Ordners
|
|
end;
|
|
|
|
function ExtractDriveChar(const FileName: String): Char;
|
|
begin
|
|
Result := FileName[1];
|
|
if Length(FileName) >= 2 then
|
|
begin
|
|
if FileName[2] <> DriveDelim then
|
|
begin
|
|
Result := #0;
|
|
end else
|
|
begin
|
|
if Length(FileName) >= 3 then
|
|
begin
|
|
if not (FileName[3] in PathDelims) then
|
|
begin
|
|
Result := #0;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function DriveCharToFileDir(DriveChar: Char): ShortString;
|
|
begin
|
|
Result := DriveChar + DriveDelim;
|
|
end;
|
|
|
|
function DriveCharToFilePath(DriveChar: Char): ShortString;
|
|
begin
|
|
Result := DriveCharToFileDir(DriveChar) + PathDelim;
|
|
end;
|
|
|
|
function DriveByteToDriveChar(DriveByte: Byte): Char;
|
|
begin
|
|
Result := Chr(DriveByte + Ord('A'));
|
|
end;
|
|
|
|
function DriveCharToDriveByte(DriveChar: Char): Byte;
|
|
begin
|
|
Result := Ord(DriveChar) - Ord('A');
|
|
end;
|
|
|
|
function DriveExists(DriveByte: Byte): Boolean;
|
|
begin
|
|
Result := (GetLogicalDrives and (1 shl DriveByte) <> 0);
|
|
end;
|
|
|
|
function GetDriveTypeChar(DriveByte: Byte): UINT;
|
|
begin
|
|
Result := GetDriveType(PChar(String(DriveCharToFilePath(DriveByteToDriveChar(DriveByte)))));
|
|
end;
|
|
|
|
function FileTimeToDateTime(FileTime: TFileTime): TDateTime;
|
|
var
|
|
LocalTime: TFileTime;
|
|
SysTime: TSystemTime;
|
|
begin
|
|
FileTimeToLocalFileTime(FileTime,LocalTime);
|
|
FileTimeToSystemTime(LocalTime,SysTime);
|
|
Result := SystemTimeToDateTime(SysTime);
|
|
end;
|
|
|
|
function ConvertFileSize(const InputSize: Int64; ConvertFactor: ShortInt = -1): Extended;
|
|
begin
|
|
{ Sollte verwendet werden mit den Umrechnungs-Faktoren, die in der globalen
|
|
"const"-Section deklariert wurden. }
|
|
Result := InputSize * Power(1024,ConvertFactor);
|
|
end;
|
|
|
|
function GetFileSize(FileName: String): Int64;
|
|
var
|
|
FileHandle: THandle;
|
|
FindData: TWIN32FINDDATA;
|
|
begin
|
|
Result := -1;
|
|
if FileExists(FileName) then
|
|
begin
|
|
FileHandle := FindFirstFile(pchar(FileName),FindData);
|
|
if FileHandle = INVALID_HANDLE_VALUE then
|
|
begin
|
|
Exit;
|
|
end;
|
|
Result := (FindData.nFileSizeHigh * (MAXDWORD)) + FindData.nFileSizeLow;
|
|
Windows.FindClose(FileHandle);
|
|
end;
|
|
end;
|
|
|
|
function GetFileModified(FileName: String): TDateTime;
|
|
var
|
|
FileHandle: THandle;
|
|
FindData: TWIN32FINDDATA;
|
|
begin
|
|
Result := StrToTime('00.00.0000 00:00:00');
|
|
if FileExists(FileName) then
|
|
begin
|
|
FileHandle := FindFirstFile(PChar(FileName),FindData);
|
|
if FileHandle = INVALID_HANDLE_VALUE then
|
|
begin
|
|
Exit;
|
|
end;
|
|
Result := FileTimeToDateTime(FindData.ftLastWriteTime);
|
|
Windows.FindClose(FileHandle);
|
|
end;
|
|
end;
|
|
|
|
function GetFileCreated(FileName: String): TDateTime;
|
|
var
|
|
FileHandle: THandle;
|
|
FindData: TWIN32FINDDATA;
|
|
begin
|
|
Result := StrToTime('00.00.0000 00:00:00');
|
|
if FileExists(FileName) then
|
|
begin
|
|
FileHandle := FindFirstFile(PChar(FileName),FindData);
|
|
if FileHandle = INVALID_HANDLE_VALUE then
|
|
begin
|
|
Exit;
|
|
end;
|
|
Result := FileTimeToDateTime(FindData.ftCreationTime);
|
|
Windows.FindClose(FileHandle);
|
|
end;
|
|
end;
|
|
|
|
function GetFileAccessed(FileName: String): TDateTime;
|
|
var
|
|
FileHandle: THandle;
|
|
FindData: TWIN32FINDDATA;
|
|
begin
|
|
Result := StrToTime('00.00.0000 00:00:00');
|
|
if FileExists(FileName) then
|
|
begin
|
|
FileHandle := FindFirstFile(PChar(FileName),FindData);
|
|
if FileHandle = INVALID_HANDLE_VALUE then
|
|
begin
|
|
Exit;
|
|
end;
|
|
Result := FileTimeToDateTime(FindData.ftLastAccessTime);
|
|
Windows.FindClose(FileHandle);
|
|
end;
|
|
end;
|
|
|
|
function GetFileAttributes(FileName: String): TFileAttributes;
|
|
var
|
|
FileHandle: THandle;
|
|
FindData: TWIN32FINDDATA;
|
|
begin
|
|
Result := [];
|
|
if FileExists(FileName) then
|
|
begin
|
|
FileHandle := FindFirstFile(PChar(FileName),FindData);
|
|
if FileHandle = INVALID_HANDLE_VALUE then
|
|
begin
|
|
Exit;
|
|
end;
|
|
if (FindData.dwFileAttributes and FILE_ATTRIBUTE_READONLY) = FILE_ATTRIBUTE_READONLY then
|
|
begin
|
|
Result := Result + [faReadOnly];
|
|
end;
|
|
if (FindData.dwFileAttributes and FILE_ATTRIBUTE_HIDDEN) = FILE_ATTRIBUTE_HIDDEN then
|
|
begin
|
|
Result := Result + [faHidden];
|
|
end;
|
|
if (FindData.dwFileAttributes and FILE_ATTRIBUTE_SYSTEM) = FILE_ATTRIBUTE_SYSTEM then
|
|
begin
|
|
Result := Result + [faSystem];
|
|
end;
|
|
if (FindData.dwFileAttributes and FILE_ATTRIBUTE_ARCHIVE) = FILE_ATTRIBUTE_ARCHIVE then
|
|
begin
|
|
Result := Result + [faArchive];
|
|
end;
|
|
if (FindData.dwFileAttributes and FILE_ATTRIBUTE_TEMPORARY) = FILE_ATTRIBUTE_TEMPORARY then
|
|
begin
|
|
Result := Result + [faTemporary];
|
|
end;
|
|
Windows.FindClose(FileHandle);
|
|
end;
|
|
end;
|
|
|
|
{ ----------------------------------------------------------------------------
|
|
TWinFileInfo
|
|
---------------------------------------------------------------------------- }
|
|
|
|
constructor TWinFileInfo.Create(AFileName: String);
|
|
begin
|
|
FFileName := AFileName;
|
|
if FileExists(FFileName) = False then
|
|
begin
|
|
raise EFileNoExist.Create('File not found: "' + FFileName + '"');
|
|
end;
|
|
end;
|
|
|
|
destructor TWinFileInfo.Destroy;
|
|
begin
|
|
//...
|
|
inherited;
|
|
end;
|
|
|
|
{ ----------------------------------------------------------------------------
|
|
TWinDrive
|
|
---------------------------------------------------------------------------- }
|
|
|
|
constructor TWinDrive.Create(ADriveChar: Char);
|
|
begin
|
|
FDriveChar := ADriveChar;
|
|
if DirectoryExists(DriveCharToFileDir(FDriveChar)) = False then
|
|
begin
|
|
raise EDriveNoExist.Create('Drive not found: "' + FDriveChar + '"');
|
|
end;
|
|
end;
|
|
|
|
destructor TWinDrive.Destroy;
|
|
begin
|
|
//...
|
|
inherited;
|
|
end;
|
|
|
|
function TWinDrive.GetSpaceTotal: Int64;
|
|
var
|
|
RootChars: array[0..4] of Char;
|
|
Root: PChar;
|
|
Dir: String;
|
|
Buffer: Int64;
|
|
begin
|
|
RootChars[0] := FDriveChar;
|
|
RootChars[1] := DriveDelim;
|
|
RootChars[2] := PathDelim;
|
|
RootChars[3] := #0;
|
|
Root := RootChars;
|
|
Dir := GetCurrentDir;
|
|
if SetCurrentDir(DriveCharToFilePath(FDriveChar)) then
|
|
begin
|
|
GetDiskFreeSpaceEx(Root,Buffer,Result,nil);
|
|
SetCurrentDir(Dir);
|
|
end else
|
|
begin
|
|
Result := -1;
|
|
end;
|
|
end;
|
|
|
|
function TWinDrive.GetSpaceFree: Int64;
|
|
var
|
|
RootChars: array[0..4] of Char;
|
|
Root: PChar;
|
|
Dir: String;
|
|
Buffer: Int64;
|
|
begin
|
|
RootChars[0] := FDriveChar;
|
|
RootChars[1] := DriveDelim;
|
|
RootChars[2] := PathDelim;
|
|
RootChars[3] := #0;
|
|
Root := RootChars;
|
|
Dir := GetCurrentDir;
|
|
if SetCurrentDir(DriveCharToFilePath(FDriveChar)) then
|
|
begin
|
|
GetDiskFreeSpaceEx(Root,Result,Buffer,nil);
|
|
SetCurrentDir(Dir);
|
|
end else
|
|
begin
|
|
Result := -1;
|
|
end;
|
|
end;
|
|
|
|
{ ----------------------------------------------------------------------------
|
|
TWinFile
|
|
---------------------------------------------------------------------------- }
|
|
|
|
constructor TWinFile.Create(AFileName: String);
|
|
begin
|
|
ExecuteMode := feOpen;
|
|
FFileName := AFileName;
|
|
FDrive := TWinDrive.Create(ExtractDriveChar(FFileName));
|
|
FInfo := TWinFileInfo.Create(FFileName);
|
|
if FileExists(FFileName) = False then
|
|
begin
|
|
raise EFileNoExist.Create('File not found: "' + FFileName + '"');
|
|
end;
|
|
end;
|
|
|
|
destructor TWinFile.Destroy;
|
|
begin
|
|
FDrive.Free;
|
|
FInfo.Free;
|
|
inherited;
|
|
end;
|
|
|
|
function TWinFile.GetExtension(WithDot: Boolean = True): String;
|
|
begin
|
|
if WithDot = True then
|
|
begin
|
|
Result := ExtractFileExt(FFileName);
|
|
end else
|
|
begin
|
|
Result := Copy(ExtractFileExt(FFileName),2,Length(ExtractFileExt(FFileName)) - 1);
|
|
end;
|
|
end;
|
|
|
|
function TWinFile.GetFileName(WithExt: Boolean = True): String;
|
|
begin
|
|
if WithExt = True then
|
|
begin
|
|
Result := ExtractFileName(FFileName); //Name + Erweiterung
|
|
end else
|
|
begin
|
|
Result := ExtractFileName(ChangeFileExt(FFileName,'')); //Nur Dateiname
|
|
end;
|
|
end;
|
|
|
|
function TWinFile.GetFolderName: String;
|
|
begin
|
|
Result := ExtractFileFolder(FFileName);
|
|
end;
|
|
|
|
function TWinFile.GetSize: Int64;
|
|
begin
|
|
Result := GetFileSize(FFileName);
|
|
end;
|
|
|
|
function TWinFile.GetPath: String;
|
|
begin
|
|
Result := ExtractFilePath(FFileName); //Gesamter Ordnerpfad (ohne Dateiname)
|
|
end;
|
|
|
|
function TWinFile.GetDir: String;
|
|
begin
|
|
Result := ExtractFileDir(FFileName);
|
|
end;
|
|
|
|
function TWinFile.GetModified: TDateTime;
|
|
begin
|
|
Result := GetFileModified(FFileName);
|
|
end;
|
|
|
|
function TWinFile.GetCreated: TDateTime;
|
|
begin
|
|
Result := GetFileCreated(FFileName);
|
|
end;
|
|
|
|
function TWinFile.GetAccessed: TDateTime;
|
|
begin
|
|
Result := GetFileAccessed(FFileName);
|
|
end;
|
|
|
|
function TWinFile.GetAttributes: TFileAttributes;
|
|
begin
|
|
Result := GetFileAttributes(FFileName);
|
|
end;
|
|
|
|
function TWinFile.GetOwner: String;
|
|
var
|
|
SecDescr: PSecurityDescriptor;
|
|
SizeNeeded, SizeNeeded2: DWORD;
|
|
OwnerSID: PSID;
|
|
OwnerDefault: BOOL;
|
|
OwnerName, DomainName: PChar;
|
|
OwnerType: SID_NAME_USE;
|
|
begin
|
|
GetMem(SecDescr,1024);
|
|
GetMem(OwnerSID,SizeOf(PSID));
|
|
GetMem(OwnerName,1024);
|
|
GetMem(DomainName,1024);
|
|
try
|
|
if GetFileSecurity(PChar(FFileName),OWNER_SECURITY_INFORMATION,SecDescr,1024,SizeNeeded) = True then
|
|
begin
|
|
if GetSecurityDescriptorOwner(SecDescr,OwnerSID,OwnerDefault) = True then
|
|
begin
|
|
SizeNeeded := 1024;
|
|
SizeNeeded2 := 1024;
|
|
if LookupAccountSID(nil,OwnerSID,OwnerName,SizeNeeded,DomainName,SizeNeeded2,OwnerType) = True then
|
|
begin
|
|
Result := OwnerName + '@' + DomainName;
|
|
end else
|
|
begin
|
|
raise ENoGetFileOwner.Create('Could not determine the file owner');
|
|
end;
|
|
end else
|
|
begin
|
|
raise ENoGetFileOwner.Create('Could not determine the file owner');
|
|
end;
|
|
end else
|
|
begin
|
|
raise ENoGetFileOwner.Create('Could not determine the file owner');
|
|
end;
|
|
finally
|
|
FreeMem(SecDescr);
|
|
FreeMem(OwnerName);
|
|
FreeMem(DomainName);
|
|
end;
|
|
end;
|
|
|
|
function TWinFile.Execute: Boolean;
|
|
begin
|
|
Result := ExecuteFile(FFileName,ExecuteMode);
|
|
end;
|
|
|
|
function TWinFile.SafeExecute: Boolean;
|
|
begin
|
|
Result := ExecuteFile(FFileName,ExecuteMode,True);
|
|
end;
|
|
|
|
end.
|