【问题标题】:.NET : How to PInvoke UpdateProcThreadAttribute.NET:如何 PInvoke UpdateProcThreadAttribute
【发布时间】:2009-09-15 13:32:14
【问题描述】:

我正在尝试在 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
);

这个声明合理吗?谢谢。

【问题讨论】:

标签: c# .net pinvoke


【解决方案1】:

您的声明存在一些问题,但出现不支持错误的问题是 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)); ?通常我的 pinvokes 没问题,但这个似乎特别可怕。我非常感谢您的回复。谢谢。
  • 非常感谢。你帮助我几乎到达那里..现在我收到错误 24(长度错误)。在上面的示例中,您谈到将 IntPtr.Size 作为 cbSize 参数传递,而在您的原始帖子中,您将其作为 IntPtr。我试过 IntPtr lpSize = Marshal.AllocHGlobal(IntPtr.Size); Marshal.WriteInt32(lpSize, IntPtr.Size) 并通过它。显然这是错误的,但我无法弄清楚正确的用法应该是什么。有任何想法吗?谢谢。
  • 抱歉,我忽略了转换。它应该是 (IntPtr)IntPtr.Size。我已经更正了帖子。
猜你喜欢
  • 1970-01-01
  • 2015-12-04
  • 2010-09-24
  • 2015-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多