英文:
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 '
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("user32.dll", EntryPoint = "CascadeWindows", 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();
}
}
}'
[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 '
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("user32.dll", EntryPoint = "CascadeWindows", 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();
}
}
}'
[Win32.Cascade]::CascadeWindows(
[IntPtr]::Zero,
[Win32.CascadeFlags]::MDITILE_SKIPDISABLED,
[IntPtr]::Zero,
[uint32] 0,
$null)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论