0

I want to execute WinAPI commands from Powershell, e.g. press button on the WPF form, the Start button hides and shows Create this code in powershell 5

Add-Type -AssemblyName PresentationFramework

[xml]$xaml = @"
<Window 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"   
        xmlns:local="clr-namespace:WinAPI"
        Height="367" Width="264" Title="Hide Start button" WindowStartupLocation="CenterScreen" ResizeMode="NoResize">
    <Grid>
        <Button x:Name = "StartButton" Content="Start button" Margin="10,60,11,0" Height="25" VerticalAlignment="Top" RenderTransformOrigin="0.5,0.5" Grid.ColumnSpan="2">
        </Button>
    </Grid>
</Window>
"@

$reader = (New-Object System.Xml.XmlNodeReader $xaml)
$window = [Windows.Markup.XamlReader]::Load($reader)
$button = $Window.FindName("StartButton")

#--------------------------------------------------------------------------------

Add-Type @"
  using System;
  using System.Runtime.InteropServices;
  public class Win32 {
    [DllImport("user32.dll")]
    public static extern IntPtr FindWindow(string ClassName, string WindowName);
    [DllImport("user32.dll")]
    public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string className, string windowName);
    [DllImport("user32.dll")]
    public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
  }
"@

$TaskbarHWnd = New-Object System.IntPtr
$StartButtonHWnd = New-Object System.IntPtr
[bool]$show = $true

$button.Add_Click({  
            $show = !($show)  
            $TaskbarHWnd = [Win32]::FindWindow("Shell_TrayWnd", $null); # get taskbar handle
            write-host $TaskbarHWnd
            $StartButtonHWnd = [Win32]::FindWindowEx($TaskbarHWnd, [IntPtr]::Zero, "Start", $null); # get start button handle - doesn't work
            write-host $StartButtonHWnd
            # hide Start button
            $result = if ($show) {0} Else {5}
            #if ($show) {$result = 0} Else {$result = 5}
            write-host $result
            [Win32]::ShowWindow($StartButtonHWnd, $result);            
})

$window.ShowDialog() | Out-Null

Command below doesn't work.

$StartButtonHWnd = [Win32]::FindWindowEx($TaskbarHWnd, [IntPtr]::Zero, "Start", $null);

The $StartButtonHWnd value = 0. Why doesn't FindWindowEx return a handle? And second question. The $show = !($show) command also doesn't work What am I doing wrong? Thanks

  • Since you already have the button in `$button`, why not simply use this in your `Add_Click` handler: `$this.Visible = !$this.Visible`? BTW variable `$show` is declared **outside** the click handler scriptblock and in there it is not visible unless you use scoping (`$script:show`) – Theo Apr 30 '21 at 14:09
  • For the window handle, try specifying the window class _and_ the name (both 'Start' in this case): `[Win32]::FindWindowEx($TaskbarHWnd, [IntPtr]::Zero, 'Start', 'Start')` – boxdog Apr 30 '21 at 14:11
  • 1
    Any reason you aren't using [UI Automation](https://learn.microsoft.com/en-us/dotnet/framework/ui-automation/) for this? – IInspectable Apr 30 '21 at 14:55
  • @Theo thanks a lot - $script:show - is working ! – himynameissergey Apr 30 '21 at 15:02
  • @boxdog thanks a lot, 'Start', 'Start' - is working ! – himynameissergey Apr 30 '21 at 15:03
  • @IInspectable, thx, i'll try UI Automation – himynameissergey Apr 30 '21 at 15:05

0 Answers0