Delphi 2009 - 获取文件的所有者名称
Delphi 2009 - Get file's Owner name
如何在 Delphi 2009 中获取文件的所有者?
我有一个函数可以像这样获取文件属性:
type
TCustomFileInfo= record
CompanyName,
Owner,
SpecialBuild: string;
procedure Clear;
end;
function GetFileInfo(const FileName: string): TCustomFileInfo;
type
PLandCodepage = ^TLandCodepage;
TLandCodepage = record
wLanguage,
wCodePage: word;
end;
var
dummy,
len: cardinal;
buf, pntr: pointer;
lang: string;
begin
len := GetFileVersionInfoSize(PChar(FileName), dummy);
if len = 0 then
RaiseLastOSError;
GetMem(buf, len);
try
if not GetFileVersionInfo(PChar(FileName), 0, len, buf) then
RaiseLastOSError;
if not VerQueryValue(buf, '\VarFileInfo\Translation\', pntr, len) then
RaiseLastOSError;
lang := Format('%.4x%.4x', [PLandCodepage(pntr)^.wLanguage, PLandCodepage(pntr)^.wCodePage]);
// Get Company's name, if available...
if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\CompanyName'), pntr, len){ and (@len <> nil)} then
result.CompanyName := PChar(pntr);
finally
FreeMem(buf);
end;
end;
...对于此 CompanyName 属性工作正常,但我不知道如何获得所有者。
此外,当我尝试对 没有文件版本号 的文件使用相同的方法时,GetFileVersionInfoSize
不起作用,这使得感觉,因为文件根本没有版本号。
是否有 GetFileVersionInfoSize
的替代方法或其他获取文件所有者的方法?我不太习惯 windows api,所以我真的不知道这是否是实现我想要的(获取所有者的名字)的正确方法。
有关文件所有权的信息未存储在版本资源中,因此您无法使用 VerQueryValue()
访问它。
所有权与文件的安全性有关,因此如果您有文件的打开句柄,则需要使用 GetFileSecurity()
or GetNamedSecurityInfo()
instead if you have a filename, or GetUserObjectSecurity()
。
无论哪种方式,您都可以提供 SECURITY_INFORMATION
value as input specifying the type of information you want to retrieve. In this case, you would use OWNER_SECURITY_INFORMATION
to request the SID of the file's owner. If successful, you can then use LookupAccountSid()
或 WMI 来获取所有者的名称。
只是为了补充 Remy 的答案,这是使用 Win32_LogicalFileOwner and Win32_LogicalFileSecuritySetting WMI 类.
获取文件所有者的示例代码
{$APPTYPE CONSOLE}
{$R *.res}
uses
SysUtils,
ActiveX,
ComObj,
Variants;
function GetFileOwner(const AFileName : string) : string;
var
LSWbemLocator, LWMIService, LObjects, LObject : OLEVariant;
FileName : string;
LEnumerator : IEnumvariant;
iValue : LongWord;
begin;
Result := '';
LSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
LWMIService := LSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
//Escape the `\` chars in the FileName value because the '\' is a reserved character in WMI.
FileName := StringReplace(AFileName, '\', '\', [rfReplaceAll]);
LObjects := LWMIService.ExecQuery(Format('ASSOCIATORS OF {Win32_LogicalFileSecuritySetting="%s"} WHERE AssocClass = Win32_LogicalFileOwner ResultRole = Owner', [FileName]));
LEnumerator := IUnknown(LObjects._NewEnum) as IEnumVariant;
if LEnumerator.Next(1, LObject, iValue) = 0 then
Result := string(LObject.AccountName); //
end;
begin
try
CoInitialize(nil);
try
Writeln(GetFileOwner('C:\Foo.Bar'));
finally
CoUninitialize;
end;
except
on E:Exception do
Writeln(E.Classname, ':', E.Message);
end;
Readln;
end.
如何在 Delphi 2009 中获取文件的所有者?
我有一个函数可以像这样获取文件属性:
type
TCustomFileInfo= record
CompanyName,
Owner,
SpecialBuild: string;
procedure Clear;
end;
function GetFileInfo(const FileName: string): TCustomFileInfo;
type
PLandCodepage = ^TLandCodepage;
TLandCodepage = record
wLanguage,
wCodePage: word;
end;
var
dummy,
len: cardinal;
buf, pntr: pointer;
lang: string;
begin
len := GetFileVersionInfoSize(PChar(FileName), dummy);
if len = 0 then
RaiseLastOSError;
GetMem(buf, len);
try
if not GetFileVersionInfo(PChar(FileName), 0, len, buf) then
RaiseLastOSError;
if not VerQueryValue(buf, '\VarFileInfo\Translation\', pntr, len) then
RaiseLastOSError;
lang := Format('%.4x%.4x', [PLandCodepage(pntr)^.wLanguage, PLandCodepage(pntr)^.wCodePage]);
// Get Company's name, if available...
if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\CompanyName'), pntr, len){ and (@len <> nil)} then
result.CompanyName := PChar(pntr);
finally
FreeMem(buf);
end;
end;
...对于此 CompanyName 属性工作正常,但我不知道如何获得所有者。
此外,当我尝试对 没有文件版本号 的文件使用相同的方法时,GetFileVersionInfoSize
不起作用,这使得感觉,因为文件根本没有版本号。
是否有 GetFileVersionInfoSize
的替代方法或其他获取文件所有者的方法?我不太习惯 windows api,所以我真的不知道这是否是实现我想要的(获取所有者的名字)的正确方法。
有关文件所有权的信息未存储在版本资源中,因此您无法使用 VerQueryValue()
访问它。
所有权与文件的安全性有关,因此如果您有文件的打开句柄,则需要使用 GetFileSecurity()
or GetNamedSecurityInfo()
instead if you have a filename, or GetUserObjectSecurity()
。
无论哪种方式,您都可以提供 SECURITY_INFORMATION
value as input specifying the type of information you want to retrieve. In this case, you would use OWNER_SECURITY_INFORMATION
to request the SID of the file's owner. If successful, you can then use LookupAccountSid()
或 WMI 来获取所有者的名称。
只是为了补充 Remy 的答案,这是使用 Win32_LogicalFileOwner and Win32_LogicalFileSecuritySetting WMI 类.
获取文件所有者的示例代码{$APPTYPE CONSOLE}
{$R *.res}
uses
SysUtils,
ActiveX,
ComObj,
Variants;
function GetFileOwner(const AFileName : string) : string;
var
LSWbemLocator, LWMIService, LObjects, LObject : OLEVariant;
FileName : string;
LEnumerator : IEnumvariant;
iValue : LongWord;
begin;
Result := '';
LSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
LWMIService := LSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
//Escape the `\` chars in the FileName value because the '\' is a reserved character in WMI.
FileName := StringReplace(AFileName, '\', '\', [rfReplaceAll]);
LObjects := LWMIService.ExecQuery(Format('ASSOCIATORS OF {Win32_LogicalFileSecuritySetting="%s"} WHERE AssocClass = Win32_LogicalFileOwner ResultRole = Owner', [FileName]));
LEnumerator := IUnknown(LObjects._NewEnum) as IEnumVariant;
if LEnumerator.Next(1, LObject, iValue) = 0 then
Result := string(LObject.AccountName); //
end;
begin
try
CoInitialize(nil);
try
Writeln(GetFileOwner('C:\Foo.Bar'));
finally
CoUninitialize;
end;
except
on E:Exception do
Writeln(E.Classname, ':', E.Message);
end;
Readln;
end.