实现IFileIsInUse

时间:2014-02-10 08:55:07

标签: winapi com

我正在尝试在我的Delphi程序中实现IFileIsUse COM接口,以便Windows资源管理器在锁定文件时可以显示有关我的应用程序的更多详细信息。 我将我的代码基于来自Microsoft(http://msdn.microsoft.com/en-us/library/ee330722%28VS.85%29.aspx)的FileIsUse示例,并且基于此:

type
  TFileIsInUseImpl = class(TInterfacedObject, IUnknown, IFileIsInUse)
  protected
    function GetAppName(out ppszName: LPWSTR) : HRESULT; stdcall;
    function GetUsage(out pfut : FILE_USAGE_TYPE) : HRESULT; stdcall;
    function GetCapabilities(out pdwCapFlags : DWORD) : HRESULT; stdcall;
    function GetSwitchToHWND(out phwnd : HWND) : HRESULT; stdcall;
    function CloseFile() : HRESULT; stdcall;
  public
    constructor Create(const AFileName: string);
  end;

procedure RegisterFileIsInUse(const AFileName: string);
var
  Cookie: Longint;
  rot: IRunningObjectTable;
  hr: HRESULT;
  mk: IMoniker;
  FileIsInUse: IFileIsInUse;
begin
  hr := GetRunningObjectTable(0, rot);
  if SUCCEEDED(hr) then
  begin
    hr := CreateFileMoniker(PChar(AFileName), mk);
    if SUCCEEDED(hr) then
    begin
      FileIsInUse := TFileIsInUseImpl.Create(AFileName);

      hr := rot.Register(ROTFLAGS_REGISTRATIONKEEPSALIVE or ROTFLAGS_ALLOWANYCLIENT, FileIsInUse, mk, Cookie);
      if hr = CO_E_WRONG_SERVER_IDENTITY then
        hr := rot.Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, FileIsInUse, mk, Cookie);
      if SUCCEEDED(hr) then
        FRegisteredFiles.Add(AFileName, TRegisteredFile.Create(Cookie, FileIsInUse));
    end;
  end;
end;

我在HKEY_CLASSES_ROOT\AppID\MyApp.exeHKEY_CLASSES_ROOT\AppID\{MyGUID}添加了注册表信息以指示RunAs=Interactive user,以便第一次调用rot.Register成功ROTFLAGS_ALLOWANYCLIENT

但是,我的TFileIsInUseImpl方法都没有被调用过。 覆盖它QueryInterface,我发现它确实被调用但仅用于编组相关接口,从不用于IFileIsInUse

环顾四周,我得出的结论是,某些内容未按照应用程序的方式进行初始化,但我无法弄清楚原因。 我已经尝试过了:

  • 致电CoInitializeEx(nil, COINIT_MULTITHREADED)而非默认CoInitialize(nil)
  • 添加HKEY_CLASSES_ROOT\CLSID\{MyGuid}\InProcServer32\ThreadingModel=Both

但没有任何帮助。考虑到Microsoft的示例是一个独立的应用程序,我应该能够复制它的功能。

你们有谁能告诉我这里我做错了什么?

1 个答案:

答案 0 :(得分:-1)