Skip optional arguments when calling DLLs via .NET assemblies in PowerShell.

huangapple go评论72阅读模式
英文:

Skip optional arguments when calling DLLs via .NET assemblies in PowerShell

问题

I am trying to call the CascadeWindows DLL from PowerShell. The documentation (https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-cascadewindows) states that there are optional parameters (an HWND/IntPtr, an array of HWND/IntPtrs, and a RECT), which can be NULL. How do I get PowerShell to call this with those parameters as NULL?

$cw = Add-Type -MemberDefinition '[DllImport("user32.dll")] public static extern ushort CascadeWindows(IntPtr hwndParent, uint wHow, IntPtr lpRect, uint cKids, IntPtr [] lpKids);' -Name 'Cascad' -Namespace 'Win32' -PassThru
# Fails with error, 'Cannot find an overload for "CascadeWindows" and the argument count: "2".'
$cw::CascadeWindows(0,0) 
# Returns 0, i.e. fails. Error code is 203, 'The system could not find the environment option that was entered.'
$cw::CascadeWindows(0,0,0,0,0) 
$gle = Add-Type -MemberDefinition '[DllImport("kernel32.dll")] public static extern uint GetLastError();' -Name 'gle' -Namespace 'Win32' -PassThru
$gle::GetLastError()
英文:

I am trying to call the CascadeWindows DLL from PowerShell. The documentation (https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-cascadewindows) states that there are optional parameters (an HWND/IntPtr, an array of HWND/IntPtrs, and a RECT), which can be NULL. How do I get PowerShell to call this with those parameters as NULL?

$cw = Add-Type -MemberDefinition '[DllImport("user32.dll")] public static extern ushort CascadeWindows(IntPtr hwndParent, uint wHow, IntPtr lpRect, uint cKids, IntPtr [] lpKids);' -Name 'Cascad' -Namespace 'Win32' -PassThru
# Fails with error, 'Cannot find an overload for "CascadeWindows" and the argument count: "2".'
$cw::CascadeWindows(0,0) 
# Returns 0, i.e. fails. Error code is 203, 'The system could not find the environment option that was entered.'
$cw::CascadeWindows(0,0,0,0,0) 
$gle = Add-Type -MemberDefinition '[DllImport("kernel32.dll")] public static extern uint GetLastError();' -Name 'gle' -Namespace 'Win32' -PassThru
$gle::GetLastError()

答案1

得分: 1

你可以在可选的 IntPtr P/Invoke 参数中使用 IntPtr.Zero

$cw::CascadeWindows(
    [IntPtr]::Zero,
    [uint32] 0,
    [IntPtr]::Zero,
    [uint32] 0,
    $null)

关于你的实现,以下是我会这样做的。请注意,[in] wHow 参数实际上是一个标志:

含义
MDITILE_SKIPDISABLED<br>0x0002 防止禁用的 MDI 子窗口被层叠。
MDITILE_ZORDER<br>0x0004 根据 Z 顺序排列窗口。如果未指定此值,则使用 lpKids 数组中指定的顺序排列窗口。
Add-Type &#39;
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;

namespace Win32
{
    [Flags]
    public enum CascadeFlags : uint
    {
        MDITILE_SKIPDISABLED = 0x0002,
        MDITILE_ZORDER = 0x0004
    }

    public static class Cascade
    {
        [DllImport(&quot;user32.dll&quot;, EntryPoint = &quot;CascadeWindows&quot;, SetLastError = true)]
        private static extern ushort NativeCascadeWindows(
            IntPtr hwndParent,
            uint wHow,
            IntPtr lpRect,
            uint cKids,
            IntPtr[] lpKids);

        public static ushort CascadeWindows(
            IntPtr hwndParent,
            CascadeFlags wHow,
            IntPtr lpRect,
            uint cKids,
            IntPtr[] lpKids)
        {
            ushort result = NativeCascadeWindows(hwndParent, (uint)wHow, lpRect, cKids, lpKids);
            if (result != 0)
            {
                return result;
            }

            throw new Win32Exception();
        }
    }
}&#39;

[Win32.Cascade]::CascadeWindows(
    [IntPtr]::Zero,
    [Win32.CascadeFlags]::MDITILE_SKIPDISABLED,
    [IntPtr]::Zero,
    [uint32] 0,
    $null)
英文:

You can use IntPtr.Zero for optional IntPtr P/Invoke parameters:

$cw::CascadeWindows(
    [IntPtr]::Zero,
    [uint32] 0,
    [IntPtr]::Zero,
    [uint32] 0,
    $null)

As for your implementation, here is how I would do it. Note that the [in] wHow argument is actually a flag:

Value Meaning
MDITILE_SKIPDISABLED<br>0x0002 Prevents disabled MDI child windows from being cascaded.
MDITILE_ZORDER<br>0x0004 Arranges the windows in Z order. If this value is not specified, the windows are arranged using the order specified in the lpKids array.
Add-Type &#39;
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;

namespace Win32
{
    [Flags]
    public enum CascadeFlags : uint
    {
        MDITILE_SKIPDISABLED = 0x0002,
        MDITILE_ZORDER = 0x0004
    }

    public static class Cascade
    {
        [DllImport(&quot;user32.dll&quot;, EntryPoint = &quot;CascadeWindows&quot;, SetLastError = true)]
        private static extern ushort NativeCascadeWindows(
            IntPtr hwndParent,
            uint wHow,
            IntPtr lpRect,
            uint cKids,
            IntPtr[] lpKids);

        public static ushort CascadeWindows(
            IntPtr hwndParent,
            CascadeFlags wHow,
            IntPtr lpRect,
            uint cKids,
            IntPtr[] lpKids)
        {
            ushort result = NativeCascadeWindows(hwndParent, (uint)wHow, lpRect, cKids, lpKids);
            if (result != 0)
            {
                return result;
            }

            throw new Win32Exception();
        }
    }
}&#39;

[Win32.Cascade]::CascadeWindows(
    [IntPtr]::Zero,
    [Win32.CascadeFlags]::MDITILE_SKIPDISABLED,
    [IntPtr]::Zero,
    [uint32] 0,
    $null)

huangapple
  • 本文由 发表于 2023年5月15日 09:58:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/76250442.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定