我一直在开发一个Outlook插件,我想拦截附件的拖放,以便我可以更改IDataObject的属性,但不知何故我的回调函数永远不会执行。我一直在使用EasyHook开放库来实现相同的目标,我已经成功地连接了一些其他常见的API,比如CreateFile等。
以下是代码快照。
公共部分类DragDrop {
private LocalHook DragDropHook;
Stack<String> Queue = new Stack<string>();
internal class HookCallbackHelper
{
public HookCallbackHelper(bool isUnicode) { IsUnicode = isUnicode; }
public bool IsUnicode;
}
private void DragDrop_Load(object sender, RibbonUIEventArgs e)
{
}
private void btnHook_Click(object sender, RibbonControlEventArgs e)
{
try
{
DragDropHook = LocalHook.Create(LocalHook.GetProcAddress("Ole32.dll", "DoDragDrop"),
new DDoDragDrop(DoDragDrop_Hooked),new HookCallbackHelper(true));
DragDropHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 });
}
catch (Exception ExtInfo)
{
System.Windows.Forms.MessageBox.Show(ExtInfo.Message);
//Interface.ReportException(ExtInfo);
return;
}
}
private int DoDragDrop_Hooked(IDataObject pDataObj, IDropSource pDropSource, uint dwOKEffects, uint[] pdwEffect)
{
System.Windows.Forms.MessageBox.Show("Hooked");
try
{
HookCallbackHelper hch = HookRuntimeInfo.Callback as HookCallbackHelper;
lock (Queue)
{
Queue.Push("[" + RemoteHooking.GetCurrentProcessId() + ":" +
RemoteHooking.GetCurrentThreadId() + "]");
}
}
catch
{
}
// call original API...
return DoDragDrop(pDataObj, pDropSource, dwOKEffects, pdwEffect);
}
[UnmanagedFunctionPointer(CallingConvention.StdCall,
CharSet = CharSet.Ansi,
SetLastError = true)]
public delegate int DDoDragDrop(
IDataObject pDataObj,
IDropSource pDropSource,
UInt32 dwOKEffects,
UInt32[] pdwEffect
);
[DllImport("Ole32.dll",
CharSet = CharSet.Unicode,
SetLastError = true,
CallingConvention = CallingConvention.StdCall)]
public static extern int DoDragDrop(IDataObject pDataObj, IDropSource pDropSource,
UInt32 dwOKEffects, UInt32[] pdwEffect);
}
[ComImport, Guid("00000121-0000-0000-C000-000000000046"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDropSource
{
[PreserveSig]
UInt32 QueryContinueDrag(
[MarshalAs(UnmanagedType.Bool)] bool fEscapePressed,
UInt32 grfKeyState);
[PreserveSig]
UInt32 GiveFeedback(
UInt32 dwEffect);
}
答案 0 :(得分:1)
我已经成功地在VSTO Startup方法中使用SetInclusiveACL();
代替SetExclusiveACL()
[DllImport("Ole32.dll")]
static extern int DoDragDrop(IDataObject pDataObj, IDropSource pDropSource, uint dwOKEffects, uint[] pdwEffect);
[UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError = true)]
[return: MarshalAs(UnmanagedType.I4)]
delegate int DragDropDelegate(IDataObject pDataObj, IDropSource pDropSource, uint dwOKEffects, uint[] pdwEffect);
private LocalHook dragDropHook;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
try
{
dragDropHook = EasyHook.LocalHook.Create(EasyHook.LocalHook.GetProcAddress("Ole32.dll", "DoDragDrop"),
new DragDropDelegate(DoDragDropHook), this);
// Only hook this thread (threadId == 0 == GetCurrentThreadId)
dragDropHook.ThreadACL.SetInclusiveACL(new Int32[] {0});
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
}
}
static int DoDragDropHook(IDataObject pDataObj, IDropSource pDropSource, uint dwOKEffects, uint[] pdwEffect)
{
//Do something...
}
更新#1
如果您需要访问CF_FORMAT,我唯一的成功就是创建一个FORMATETC并将其传递给GetData
方法。下面我将其设置为&#39; FileContents&#39;格式
FORMATETC format = new FORMATETC();
format.cfFormat = (short)DataFormats.GetFormat("FileContents").Id;
format.dwAspect = DVASPECT.DVASPECT_CONTENT;
format.lindex = 0;
format.ptd = new IntPtr(0);
format.tymed = TYMED.TYMED_HGLOBAL | TYMED.TYMED_ISTREAM | TYMED.TYMED_ISTORAGE;
STGMEDIUM medium = new STGMEDIUM();
pDataObj.GetData(ref format, out medium);
有关参考,请参阅https://msdn.microsoft.com/en-us/library/windows/desktop/ms678431(v=vs.85).aspx
答案 1 :(得分:-1)
这正是您为当前进程启用挂钩所需要的:
DragDropHook.ThreadACL.SetInclusiveACL(new Int32[] { 0 });
要禁用当前进程的挂钩,请调用:
DragDropHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 });