德尔福WPD事件回调 - 获取文件名

问题描述:

我试图跟踪何时WPD兼容设备上创建文件,如数码相机或Android手机。我注册接收Advice的事件,并且我的回调调用正确,但我无法正确获取文件名(可能是OBJECT_NAME)。这里是我有:德尔福WPD事件回调 - 获取文件名

TPortableDeviceEventsCallback = class(TInterfacedObject, IPortableDeviceEventCallback) 
public 
    function OnEvent(const pEventParameters: IPortableDeviceValues): HResult; dynamic; stdcall; 
end; 
. 
. 
. 
function TPortableDeviceEventsCallback.OnEvent(const pEventParameters: IPortableDeviceValues): HResult; 
var 
ObjName: PWideChar; 
begin 
    pEventParameters.GetStringValue(WPD_EVENT_PARAMETER_OBJECT_NAME, ObjName); 
    Log(string(ObjName)); 
end; 

我只得到垃圾,而不是添加/删除的对象名称。我在这里错过了什么?

首先,OnEvent()不应声明为dynamic。在IPortableDeviceEventCallback已经是virtual

其次,你没有在IPortableDeviceValues.GetStringValue()上做任何错误处理,或释放它返回的内存。它应该看起来更像是这样的:

function TPortableDeviceEventsCallback.OnEvent(const pEventParameters: IPortableDeviceValues): HResult; 
var 
    Hr: HResult; 
    ObjName: PWideChar; 
begin 
    Hr := pEventParameters.GetStringValue(WPD_EVENT_PARAMETER_OBJECT_NAME, ObjName); 
    case Hr of 
    S_OK: begin 
     try 
     Log('Object Name: ' + String(ObjName)); 
     finally 
     CoTaskMemFree(ObjName); 
     end; 
    end; 
    DISP_E_TYPEMISMATCH: begin 
     Log('Object Name is not a string!'); 
    end; 
    $80070490: // HRESULT_FROM_WIN32(ERROR_NOT_FOUND) 
    begin 
     Log('Object Name is not found!'); 
    end; 
    else 
    // some other error 
    Log('Error getting Object Name: $' + IntToHex(Hr, 8)); 
    end; 
    Result := S_OK; 
end; 

第三,你是不是看WPD_EVENT_PARAMETER_EVENT_ID参数的值(这是唯一的必需参数)知道你才能知道什么参数都可以收到什么事件用它。不同的事件具有不同的参数值。

尝试枚举可用的值,看看有什么你实际上是在每个事件接收:

function TPortableDeviceEventsCallback.OnEvent(const pEventParameters: IPortableDeviceValues): HResult; 
var 
    Hr: HResult; 
    Count, I: DWORD; 
    Key: PROPERTYKEY; 
    Value: PROPVARIANT; 
begin 
    Log('Event received'); 

    Hr := pEventParameters.GetCount(Count); 
    if FAILED(Hr) or (Count = 0) then Exit; 

    Log('Param count: ' + IntToStr(Count)); 

    for I := 0 to Count-1 do 
    begin 
    Hr := pEventParameters.GetAt(I, Key, Value); 
    if FAILED(Hr) then 
    begin 
     Log('Cant get parameter at index ' + IntToStr(I)); 
     Continue; 
    end; 
    try 
     Log('Param Key: ' + GuidToString(Key.fmtid) + ', Value type: $' + IntToHex(Value.vt, 4)); 
     // log content of Value based on its particular data type as needed... 
    finally 
     PropVariantClear(Value); 
    end; 
    end; 
    Result := S_OK; 
end; 
+0

很多很多的感谢。我会将所有这些更改应用于我的代码。但问题是,假设我收到了WPD_EVENT_OBJECT_ADDED事件,这是获取添加的文件的名称的正确方法吗?为什么我要垃圾? –

+0

好吧!我意识到我正在使用错误的常量。现在我可以使用WPD_OBJECT_ORIGINAL_FILE_NAME获取正确的文件名。 –