下面这段代码在32位的机器上运行正常,m_hDrop能渠道正确的值,但是在64位win7系统上m_hDrop总是0,Any CPU 和 X64 两种编译方式都返回的是0
[StructLayout(LayoutKind.Sequential)]
    public struct FORMATETC
    {
        public CLIPFORMAT cfFormat;
        public uint ptd;
        public DVASPECT dwAspect;
        public int lindex;
        public TYMED tymed;
    }[StructLayout(LayoutKind.Sequential)]
    public struct STGMEDIUM
    {
        public uint tymed;
        public uint hGlobal;
        public uint pUnkForRelease;
    }int IShellExtInit.Initialize(IntPtr pidlFolder, IntPtr lpdobj, uint hKeyProgID)
        {
            try
            {
                m_dataObject = null;
                if (lpdobj != (IntPtr)0)
                {
                    m_dataObject = (ShellLib.IDataObject)Marshal.GetObjectForIUnknown(lpdobj);
                    FORMATETC fmt = new FORMATETC();
                    fmt.cfFormat = CLIPFORMAT.CF_HDROP;
                    fmt.ptd = 0;
                    fmt.dwAspect = DVASPECT.DVASPECT_CONTENT;
                    fmt.lindex = -1;
                    fmt.tymed = TYMED.TYMED_HGLOBAL;
                    STGMEDIUM medium = new STGMEDIUM();
                    m_dataObject.GetData(ref fmt, ref medium);
                    m_hDrop = medium.hGlobal;
                    MessageBox.Show(m_hDrop.ToString());
                }
            }
            catch (Exception)
            {
            }
            return S_OK;
        }
哪位大哥遇到过类似的问题或者能解决的帮个忙,谢谢了!C#C++IShellExtInit.net

解决方案 »

  1.   

    这两天正好碰到这个问题,扯的是互联网上没有找到任何一个真正的回答。最接近的是这个
    http://bbs.csdn.net/topics/300128303
    但是这个的回答也不正确的,一样误导人,二楼的回复的能正常的代码是因为他用的c++。这个问题我折腾了两天,还是给互联网上留个真正的答案吧:
    这个问题其实非常简单,只是我们用C#的时候往往会进入盲区,如果用C的话反而会很快注意到问题的真相,或者说根本不需要注意到。
    真正的问题在于结构的内存布局。你看看FORMATETC和STGMEDIUM,里面都有uint或int,这就是问题所在。托管代码中,无论是32位还是64位。uint和int都是4字节,而非托管部分,确切说就是windows内部的已经是8字节了。你传给m_dataObject.GetData(ref fmt, ref medium);这一句的两个结构的内存布局都不同,很显然是无法得到正确的m_hDrop的(0),然后后面获取不到正确的文件也就顺理成章了。
    解决方法就是将所有uint改UIntPtr,int改IntPtr,这样最后的代码能自适应32位和64位。那个帖子楼主说的UIntPtr改IntPtr什么的完全是没有必要的。无论UIntPtr还是IntPtr,对机器来说,都是一模一样的数据。
    然后,第三个参数0xFFFFFFFF,这个根据上面的分析也应该是错误的,除非微软特意为了兼容这个代码,指定这个64位int等于0xffffffff的时候会做特殊处理。真正应该传的值是-1。好吧,这个我没验证。折腾两天了,已经没激情了,现在就想把代码赶快画完。