我正在尝试在我的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.exe
和HKEY_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的示例是一个独立的应用程序,我应该能够复制它的功能。
你们有谁能告诉我这里我做错了什么?
答案 0 :(得分:-1)
如果代码的构建类似于MSDN示例,则它按预期工作。示例代码可以从代码库中下载:
新链接:https://msdn.microsoft.com/en-us/library/windows/desktop/ee330722(v=vs.85).aspx 从Windows 7 SDK下载:https://www.microsoft.com/en-us/download/details.aspx?id=8279