【问题标题】:Delphi 2009 - Get file's Owner nameDelphi 2009 - 获取文件的所有者名称
【发布时间】:2017-03-07 19:53:48
【问题描述】:

如何在 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,所以我真的不知道这是否是实现我想要的正确方法(获取所有者的名字)。

【问题讨论】:

  • 这是你想要的文件系统属性?
  • GetFileVersionInfoSize() 返回 0 不是错误,除非GetLastError() 表示实际发生了错误。 RaiseLastOSError() 将始终引发 EOSError 异常,即使 GetLastError() 返回 0。
  • @DavidHeffernan 我拍了张照片,可惜是葡萄牙语,不过我想你能看懂:picture
  • @RemyLebeau 说得好。我对 doesn't work 的意思是它像你说的那样返回零,我认为这是没有版本号的文件的预期行为。我想获得一些 XML 文件的所有者...

标签: delphi winapi delphi-2009


【解决方案1】:

关于文件所有权的信息不存储在版本资源中,因此您不能使用VerQueryValue() 访问它。

所有权与文件的安全性有关,因此如果您有文件名,则需要使用GetFileSecurity()GetNamedSecurityInfo(),如果您有文件的打开句柄,则需要使用GetUserObjectSecurity()

无论哪种方式,您都可以提供SECURITY_INFORMATION 值作为输入,指定您要检索的信息类型。在这种情况下,您将使用OWNER_SECURITY_INFORMATION 来请求文件所有者的 SID。如果成功,您可以使用LookupAccountSid() 或 WMI 获取所有者的姓名。

【讨论】:

  • 在你回答之后,我搜索了GetFileSecurity()的用法示例,发现this sample。我可以得到用户和域,谢谢你的帮助!
【解决方案2】:

只是为了补充 Remy 的答案,这是使用 Win32_LogicalFileOwnerWin32_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.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-20
    • 1970-01-01
    • 1970-01-01
    • 2021-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多