Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why do I see a boolean value from EnumChildWindows when using this Powershell script?

A friend has a problem on his work PC. There are frequent network issues, after which he sees dozens of error popup windows from File Explorer. He wants a PowerShell script to close them all down without having to click each one individually. I solved the problem in Python but he must have a PowerShell script and I’m a PowerShell novice.

I found this example: https://stackoverflow.com/questions/64469727/powershell-and-winapi-enumwindows-function

and I cobbled together the following script, to help me understand what I need to do.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel


function Get-ChildWindowHandles {

    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [IntPtr]$ParentWindowHandle
    )

    $MemberDefinition = @"
// declare the EnumChildWindowsProc delegate type
public delegate bool EnumChildWindowsProc(IntPtr hWnd, IntPtr lParam);

[DllImport("user32.dll")]
public static extern bool EnumChildWindows(IntPtr hWnd, EnumChildWindowsProc enumProc, IntPtr lParam);
"@

    Add-Type -MemberDefinition $MemberDefinition -Name EnumChildWindowsUtil -Namespace Win32Functions

    # Create a list to act as a receptacle for all the window handles we're about to enumerate
    $ChildWindowHandles = [System.Collections.Generic.List[IntPtr]]::new()

    # Define the callback function
    $callback = {
        param([IntPtr]$handle, [IntPtr]$param) 

        # Copy the window handle to our list
        $ChildWindowHandles.Add($handle)

        # Continue (return $false from the callback to abort the enumeration)
        return $true
    }

    [Win32Functions.EnumChildWindowsUtil]::EnumChildWindows($ParentWindowHandle, $callback, [IntPtr]::Zero)

    return $ChildWindowHandles
}

$com_object = New-Object -com "Shell.Application"
$windows = $com_object.windows()
foreach ($w in $windows) {
    if ($w.Name -eq 'File Explorer') {
        $handles = Get-ChildWindowHandles -ParentWindowHandle $w.HWND
        foreach ($handle in $handles) {
            Write-Output "handle.GetType $($handle.GetType()) handle $($handle)"
        }
    }
}

It returns this:

handle.GetType bool handle True
handle.GetType System.IntPtr handle 591506
handle.GetType System.IntPtr handle 591192
handle.GetType System.IntPtr handle 722370
...

Why is the first element a boolean? I’d be very grateful if someone could explain what I’m doing wrong.

As an aside, why aren’t File Explorer windows seen when I try
Get-Process | Where-Object {$_.MainWindowTitle} #| Select-Object MainWindowTitle?

Thanks in advance for any help
Chris

>Solution :

EnumChildWindows returns a BOOL according to https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enumchildwindows:

BOOL EnumChildWindows(
^^^^
  [in, optional] HWND        hWndParent,
  [in]           WNDENUMPROC lpEnumFunc,
  [in]           LPARAM      lParam
);

That return value isn’t being captured in your function so it’s being returned implicitly as part of the function’s output stream.

You can capture it with:

$null = [Win32Functions.EnumChildWindowsUtil]::EnumChildWindows( ... )
^^^^^^^

and it’ll no longer appear in the function return values.

Other options to do the same thing are:

[void] [Win32Functions.EnumChildWindowsUtil]::EnumChildWindows( ... )
^^^^^^

or

[Win32Functions.EnumChildWindowsUtil]::EnumChildWindows( ... ) | Out-Null
                                                               ^^^^^^^^^^

but $null = is my own personal stylistic preference

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading