1

I'm trying to use the script given in this answer Setting window size and position in PowerShell 5 and 6

to set the height and size of multiple windows explorer windows. Not the internet explroer.. the file browser called 'explorer'.

it works with the program 'notepad'. but not with the program 'explorer'.

#works
Set-Window -ProcessName notepad-X 400 -Y 400 -Width 400 -Height 700 

#doesnt work
Set-Window -ProcessName explorer -X 400 -Y 400 -Width 400 -Height 700

ideally I'd like to have a script:

  1. open 3 explorer windows.
  2. navigate to filepath A,B,C
  3. resize each window to a specific location on the screen

How can I do this without installing any extra software and just use raw powershell here?

EDIT: After using harrymc's suggestion, I've gotten halfway through the problem.. I can move the window but I just need to figure out how to get the handle of 3 explorer child processes...

$MethodDefinition = @'
[DllImport("user32.dll")]
public extern static bool MoveWindow(IntPtr handle, int x, int y, int width, int height, bool redraw);
'@

$Kernel32 = Add-Type -MemberDefinition $MethodDefinition -Name 'Kernel32' -Namespace 'Win32' -PassThru

# How do I get 3 child explorer IDs here?
# i can't pass in 'explorer' name because that references the parent process running the whole GUI
$Handle = (Get-Process -Name "notepad").MainWindowHandle

$Return = [Window]::MoveWindow($Handle, 10, 20, 400, 400,$True)

Edit 2:

I've tried getting the explorer window through the Start-Process function but I am receiving an error:

$er3 = (Start-Process explorer -passthru)

PS C:\> (Get-Process -Id $er3.Id).MainWindowHandle
Get-Process : Cannot find a process with the process identifier 10572.At line:1 char:2
+ (Get-Process -Id $er3.Id).MainWindowHandle
+  ~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (10572:Int32) [Get-Process], ProcessCommandException
    + FullyQualifiedErrorId : NoProcessFoundForGivenId,Microsoft.PowerShell.Commands.GetProcessCommand

it says it has exited... but the explorer filebrowser window stays open... not sure whats going on here. If i try it with notepad it works...

$er4 = (Start-Process notepad -passthru)
PS C:\> (Get-Process -Id $er4.Id).MainWindowHandle
9899994

Edit 3: I've figured it out using the ComObject, and accessing item(0).

$ex4 = New-Object -ComObject Shell.Application
$ex4.open("C:\")
# $ex4.windows()[0].Width = 400       # breaks
$ex5 = $ex4.Windows()[0]
$ex6 = $ex5.Item(0)              # not sure why i need to do this extra step
$ex6.Width = 400 
$ex6.Navigate("file:///C:/Folder1/Folder2")                                                   
0

It should be possible by using native Windows API. Something like this:

[DllImport("User32.dll")]
public extern static bool MoveWindow(IntPtr handle, int x, int y, int width, int height, bool redraw);
...
$Handle = (Get-Process -Id $ProcessId).MainWindowHandle
$Return = [Window]::MoveWindow($Handle, $x, $y, $Width, $Height,$True)

As this general code does not work for Explorer, here is an alternative solution (tested):

$ex1 = New-Object -ComObject Shell.Application
$ex1.open("C:\")
$ex1.windows()[0].Top = 10
# also assignable : Left, Width, Height
# if required : $handle = $ex1.windows()[0].HWND
  • How do I get the processId for a child explorer process? The way i understand it, if i open up ctrl+alt+del task manager, i see one explorer process running (which is the process that shows the whole GUI on windows pretty much right?) I just want to select one of the small explorer windows located on my taskbar. – Ryu S. Dec 17 '18 at 4:25
  • ok I foudn out how to get the Id of an explorer process but getting its handle is causign an error... updated the question with an example output – Ryu S. Dec 17 '18 at 4:40
  • Explorer seems to be the exception here, so I added an alternative that works. – harrymc Dec 17 '18 at 9:33
  • hmm I get an error when trying to set top, width etc... see updated question – Ryu S. Dec 17 '18 at 10:02
  • I've figured it out , I had to add an additional step where I accessed the object using items(0) – Ryu S. Dec 17 '18 at 10:16
0

PowerShell is really not a UI automation tool. As per what you pointed to, why not just use...

UiAutomation

$w = Get-UIAWindow -ProcessName notepad
$w.Move(100, 100)

Project Description

The UIAutomation module simplifies software testing automation when you are working on GUI tests. Based on the UI Automation library that is a part of .Net Framework since 3.0, the module is intended to make life of software engineers as easy as it may be.

WASP

WASP is a PowerShell snapin for Windows Automation tasks like selecting windows and controls and sending mouse and keyboard events. We have cmdlets like Select-Window, Select-Control, Send-Keys, Send-Click, Get-WindowPosition, Set-WindowPosition, Set-WindowActive, Remove-Window

Note: These are no longer maintained, but it still works as designed and the fact you are using sample code that has never been or will ever be maintained.

See also this fully maintained solution:

AutoIT

The newest versions of the AutoIt scripting language now come with a bonus for PowerShell users. A set of native PowerShell Cmdlets! This allows you to add the unique features of AutoIt – window manipulation and keystroke simulation – to your usual PowerShell scripts. As an additional bonus, the AutoIt PowerShell Cmdlets and Assemblies are digitally signed so they can be used with the more strict execution policies. The Cmdlets will also run natively with x86 and x64 versions of PowerShell!

  • Due to the operational requirements, the system I'm using is a plain vanilla machine with no ability to install custom software from the internet – Ryu S. Dec 17 '18 at 4:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.