.NET:如何使用PInvoke更新UpdateProcThreadAttribute

3

我在尝试在Windows 7上调用PInvoke UpdateProcThreadAttribute(),但我的尝试一直返回FALSE,并显示最后的Win32错误代码为50。

Function declaration (from MSDN)

BOOL WINAPI UpdateProcThreadAttribute(
  __inout    LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList,
  __in       DWORD dwFlags,
  __in       DWORD_PTR Attribute,
  __in       PVOID lpValue,
  __in       SIZE_T cbSize,
  __out_opt  PVOID lpPreviousValue,
  __in_opt   PSIZE_T lpReturnSize
);

这里是我对PInvoke签名的尝试:
[DllImport("kernel32.dll", CallingConvention = CallingConvention.Winapi, SetLastError = true)]
public static extern bool UpdateProcThreadAttribute
(
            IntPtr lpAttributeList,
            UInt32 dwFlags,
            ref UInt32 Attribute,
            ref IntPtr lpValue,
            ref IntPtr cbSize,
            IntPtr lpPreviousValue,
            IntPtr lpReturnSize
);

这个声明有意义吗?谢谢。


检查这类问题,访问http://www.pinvoke.net/通常是值得的。 - Ian Ringrose
1个回答

2
你的声明有几个问题,但导致“不支持”错误的问题是Attribute参数。DWORD_PTR不是指针,而是指针大小的无符号整数,因此应该使用IntPtr而不是ref uint。
我会使用以下声明:
    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool UpdateProcThreadAttribute(
        IntPtr lpAttributeList, uint dwFlags, IntPtr Attribute,
        IntPtr lpValue, IntPtr cbSize, IntPtr lpPreviousValue, 
        IntPtr lpReturnSize);

编辑:

我试着在评论中写这个,但它不能很好地处理代码。

对于一个进程句柄,你需要一个IntPtr来持有这个句柄。所以你需要像这样的东西:

IntPtr hProcess //previously retrieved.
IntPtr lpAttributeList //previously allocated using InitializeProcThreadAttributeList and Marshal.AllocHGlobal.

const int PROC_THREAD_ATTRIBUTE_PARENT_PROCESS = 0x00020000;
IntPtr lpValue = Marshal.AllocHGlobal(IntPtr.Size); 
Marshal.WriteIntPtr(lpValue, hProcess);
if(UpdateProcThreadAttribute(lpAttributeList, 0, (IntPtr)PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, lpValue, (IntPtr)IntPtr.Size, IntPtr.Zero, IntPtr.Zero))
{
    //do something
}

//Free lpValue only after the lpAttributeList is deleted.

谢谢您。我已经更新了签名,但仍然得到50的错误。您建议如何设置lpValue来保存进程的句柄?我将其设置为IntPtr(例如pHandle),那么我是否可以直接传递它,并且对于cbSize,我应该做类似这样的事情:IntPtr pSize =(System.IntPtr)(Marshal.SizeOf(pHandle))?通常我的PInvoke都没问题,但这个似乎特别棘手。非常感谢您的回复。谢谢。 - mrbouffant
非常感谢。你几乎帮助我走到了尽头。现在我遇到了错误24(长度不好)。在你上面的示例中,你提到要将IntPtr.Size作为cbSize参数传递,而在你的原始帖子中,它是一个IntPtr类型的。我尝试使用IntPtr lpSize = Marshal.AllocHGlobal(IntPtr.Size); Marshal.WriteInt32(lpSize, IntPtr.Size)并通过传递它来解决问题。显然这是错误的,但我无法弄清楚正确的用法应该是什么。有什么想法吗?谢谢。 - mrbouffant
抱歉,我漏掉了转换。应该是(IntPtr)IntPtr.Size。我已经更正了帖子。 - Stephen Martin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接