• This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.

How to position the PowerShell window on screen?

M

Marc Scheuner

#1
Folks,

Another potentially embarrassing and stupid question: how can I add
some Powershell magic lines of code to my profile so that the
PowerShell window appears in the bottom right hand corner of my
screen? (preferably these lines should be so smart as to deal with
various screen resolutions, too - on my notebook and my 24" desktop
screen, for instance).

I looked at various properties of $Host, $Host.UI, $Host.UI.RawUI, but
couldn't really figure out anything that seemed to make sense......

Thanks for any hints and pointers!
Marc
 

My Computer

J
#2
On Jan 23, 1:03 pm, Marc Scheuner <no.s...@xxxxxx> wrote:

> Folks,
>
> Another potentially embarrassing and stupid question: how can I add
> some Powershell magic lines of code to my profile so that the
> PowerShell window appears in the bottom right hand corner of my
> screen? (preferably these lines should be so smart as to deal with
> various screen resolutions, too - on my notebook and my 24" desktop
> screen, for instance).
>
> I looked at various properties of $Host, $Host.UI, $Host.UI.RawUI, but
> couldn't really figure out anything that seemed to make sense......
>
> Thanks for any hints and pointers!
> Marc
Marc,

I decided to work out a way to do this, but I have to warn you that
this isn't exactly a simple solution. This is one of those situations
that I hope someone else out there has a much easier way of doing
this. I ended up using Win32 API functions through some C# code that
I compile at run-time. I tried to make the Window functions fairly
general in case you might have any other uses for them.

This creates an assembly in your $home directory that contains the
compiled C# code. The complexity of this solution comes from needing
to account for where the taskbar is, and whether or not its "Auto-
hide" setting is set.

Here you go. I hope at least you have a good laugh over it.

# Move-Window

$cSharpCodeProvider = `
New-Object Microsoft.CSharp.CSharpCodeProvider

$parameters = `
New-Object System.CodeDom.Compiler.CompilerParameters
$parameters.GenerateInMemory = $true
$parameters.GenerateExecutable = $false
$parameters.OutputAssembly = "Custom.dll"

# create a strongly-named assembly
$cr = $cSharpCodeProvider.CompileAssemblyFromSource( $parameters,
@"
using System;
using System.Runtime.InteropServices;

namespace Win32Api
{
public class WindowSizeUtilities
{
private enum ApplicationBarMessage : int
{
GetState = 4,
GetTaskBarPosition = 5
}

private enum ApplicationBarState : int
{
Manual,
AutoHide,
AlwaysOnTop,
AutoHideAndOnTop,
}

public enum ApplicationBarEdge : int
{
Left,
Top,
Right,
Bottom
}

[StructLayout(LayoutKind.Sequential)]
private struct ApplicationBarData
{
public int Size;
public IntPtr Handle;
public int CallbackMessage;
public ApplicationBarEdge Edge;
public Rectangle Rectangle;
public IntPtr Param;
}

[StructLayout(LayoutKind.Sequential)]
public struct Rectangle
{
public int X;
public int Y;
public int Left;
public int Bottom;
}

[DllImport("shell32")]
static extern uint SHAppBarMessage(
ApplicationBarMessage dwMessage,
ref ApplicationBarData pData );

[DllImport("user32.dll")]
public static extern bool GetWindowRect(
IntPtr hWnd,
out Rectangle rectangle );

[DllImport("user32.dll")]
public static extern int SetWindowPos(
IntPtr hWnd,
IntPtr hWndInsertAfter,
int x,
int y,
int cx,
int cy,
uint uFlags );

public static void GetTaskBarPosition(
ref bool autoHide,
ref ApplicationBarEdge edge,
ref int x,
ref int y,
ref int width,
ref int height )
{
ApplicationBarData applicationBarData =
new ApplicationBarData();

uint result =
SHAppBarMessage(
ApplicationBarMessage.GetState,
ref applicationBarData );

switch ( (ApplicationBarState)result )
{
case ApplicationBarState.Manual:
case ApplicationBarState.AlwaysOnTop:
autoHide = false;
break;
case ApplicationBarState.AutoHide:
case ApplicationBarState.AutoHideAndOnTop:
autoHide = true;
break;
default:
autoHide = false;
break;
}

applicationBarData =
new ApplicationBarData();

SHAppBarMessage(
ApplicationBarMessage.GetTaskBarPosition,
ref applicationBarData );

edge = applicationBarData.Edge;

x = applicationBarData.Rectangle.X;
y = applicationBarData.Rectangle.Y;
width = applicationBarData.Rectangle.Left -
applicationBarData.Rectangle.X;
height = applicationBarData.Rectangle.Bottom -
applicationBarData.Rectangle.Y;
}

public static void GetWindowPosition(
IntPtr hWnd,
ref int x,
ref int y,
ref int width,
ref int height )
{
Rectangle windowRectangle = new Rectangle();
GetWindowRect( hWnd, out windowRectangle );

x = windowRectangle.X;
y = windowRectangle.Y;
width = windowRectangle.Left - windowRectangle.X;
height = windowRectangle.Bottom - windowRectangle.X;
}

public static void SetWindowPosition(
IntPtr hWnd,
int x,
int y,
int width,
int height,
uint uFlags )
{
SetWindowPos(
hWnd,
(IntPtr)null,
x, y,
width, height,
(uint)uFlags );
}
}
}
"@ )

$taskbarAutoHide = $false
$taskbarEdge = 0
$taskbarX = 0
$taskbarY = 0
$taskbarWidth = 0
$taskbarHeight = 0

# get the taskbar position information
[Win32Api.WindowSizeUtilities]::GetTaskBarPosition(
[ref]$taskbarAutoHide,
[ref]$taskbarEdge,
[ref]$taskbarX,
[ref]$taskbarY,
[ref]$taskbarWidth,
[ref]$taskbarHeight )

# get the PowerShell window handle
$powershellHandle = ( Get-Process "powershell" ).MainWindowHandle

$powershellX = 0
$powershellY = 0
$powershellWidth = 0
$powershellHeight = 0

# get the position of the PowerShell window
[Win32Api.WindowSizeUtilities]::GetWindowPosition(
$powershellHandle,
[ref]$powershellX,
[ref]$powershellY,
[ref]$powershellWidth,
[ref]$powershellHeight )

# get the primary monitor information
$screen = [System.Windows.Forms.Screen]::PrimaryScreen

# work out the new position
$newX = 0
$newY = 0

# convert to int for easier comparison
# Left = 0
# Top = 1
# Right = 2
# Bottom = 3
$taskbarEdge = [int]$taskbarEdge

if ( !$taskbarAutoHide -and
( $taskbarEdge -eq 2 -or $taskbarEdge -eq 3 ) )
{
if ( $taskbarEdge -eq 2 )
{
$newX = $screen.Bounds.Width -
$powershellWidth -
$taskbarWidth
$newY = $screen.Bounds.Height -
$powershellHeight
}
else
{
$newX = $screen.Bounds.Width -
$powershellWidth
$newY = $screen.Bounds.Height -
$powershellHeight -
$taskbarHeight
}
}
else
{
$newX = $screen.Bounds.Width - $powershellWidth
$newY = $screen.Bounds.Height - $powershellHeight
}

# move the window!
[Win32Api.WindowSizeUtilities]::SetWindowPosition(
$powershellHandle,
$newX,
$newY,
-1, # cx
-1, # cy
0x0001 # SWP_NOSIZE - retains the current size -
# ignores the width and height parameters
)

Have fun!

Jeff Hillman
 

My Computer

J
#3
On Jan 23, 6:42 pm, Jeff <jeff.hill...@xxxxxx> wrote:

> On Jan 23, 1:03 pm, Marc Scheuner <no.s...@xxxxxx> wrote:
>

> > Folks,
>

> > Another potentially embarrassing and stupid question: how can I add
> > some Powershell magic lines of code to my profile so that the
> > PowerShell window appears in the bottom right hand corner of my
> > screen? (preferably these lines should be so smart as to deal with
> > various screen resolutions, too - on my notebook and my 24" desktop
> > screen, for instance).
>

> > I looked at various properties of $Host, $Host.UI, $Host.UI.RawUI, but
> > couldn't really figure out anything that seemed to make sense......
>

> > Thanks for any hints and pointers!
> > Marc
>
> Marc,
>
> I decided to work out a way to do this, but I have to warn you that
> this isn't exactly a simple solution. This is one of those situations
> that I hope someone else out there has a much easier way of doing
> this. I ended up using Win32 API functions through some C# code that
> I compile at run-time. I tried to make the Window functions fairly
> general in case you might have any other uses for them.
>
> This creates an assembly in your $home directory that contains the
> compiled C# code. The complexity of this solution comes from needing
> to account for where the taskbar is, and whether or not its "Auto-
> hide" setting is set.
>
> Here you go. I hope at least you have a good laugh over it.
>
> # Move-Window
>
> $cSharpCodeProvider = `
> New-Object Microsoft.CSharp.CSharpCodeProvider
>
> $parameters = `
> New-Object System.CodeDom.Compiler.CompilerParameters
> $parameters.GenerateInMemory = $true
> $parameters.GenerateExecutable = $false
> $parameters.OutputAssembly = "Custom.dll"
>
> # create a strongly-named assembly
> $cr = $cSharpCodeProvider.CompileAssemblyFromSource( $parameters,
> @"
> using System;
> using System.Runtime.InteropServices;
>
> namespace Win32Api
> {
> public class WindowSizeUtilities
> {
> private enum ApplicationBarMessage : int
> {
> GetState = 4,
> GetTaskBarPosition = 5
> }
>
> private enum ApplicationBarState : int
> {
> Manual,
> AutoHide,
> AlwaysOnTop,
> AutoHideAndOnTop,
> }
>
> public enum ApplicationBarEdge : int
> {
> Left,
> Top,
> Right,
> Bottom
> }
>
> [StructLayout(LayoutKind.Sequential)]
> private struct ApplicationBarData
> {
> public int Size;
> public IntPtr Handle;
> public int CallbackMessage;
> public ApplicationBarEdge Edge;
> public Rectangle Rectangle;
> public IntPtr Param;
> }
>
> [StructLayout(LayoutKind.Sequential)]
> public struct Rectangle
> {
> public int X;
> public int Y;
> public int Left;
> public int Bottom;
> }
>
> [DllImport("shell32")]
> static extern uint SHAppBarMessage(
> ApplicationBarMessage dwMessage,
> ref ApplicationBarData pData );
>
> [DllImport("user32.dll")]
> public static extern bool GetWindowRect(
> IntPtr hWnd,
> out Rectangle rectangle );
>
> [DllImport("user32.dll")]
> public static extern int SetWindowPos(
> IntPtr hWnd,
> IntPtr hWndInsertAfter,
> int x,
> int y,
> int cx,
> int cy,
> uint uFlags );
>
> public static void GetTaskBarPosition(
> ref bool autoHide,
> ref ApplicationBarEdge edge,
> ref int x,
> ref int y,
> ref int width,
> ref int height )
> {
> ApplicationBarData applicationBarData =
> new ApplicationBarData();
>
> uint result =
> SHAppBarMessage(
> ApplicationBarMessage.GetState,
> ref applicationBarData );
>
> switch ( (ApplicationBarState)result )
> {
> case ApplicationBarState.Manual:
> case ApplicationBarState.AlwaysOnTop:
> autoHide = false;
> break;
> case ApplicationBarState.AutoHide:
> case ApplicationBarState.AutoHideAndOnTop:
> autoHide = true;
> break;
> default:
> autoHide = false;
> break;
> }
>
> applicationBarData =
> new ApplicationBarData();
>
> SHAppBarMessage(
> ApplicationBarMessage.GetTaskBarPosition,
> ref applicationBarData );
>
> edge = applicationBarData.Edge;
>
> x = applicationBarData.Rectangle.X;
> y = applicationBarData.Rectangle.Y;
> width = applicationBarData.Rectangle.Left -
> applicationBarData.Rectangle.X;
> height = applicationBarData.Rectangle.Bottom -
> applicationBarData.Rectangle.Y;
> }
>
> public static void GetWindowPosition(
> IntPtr hWnd,
> ref int x,
> ref int y,
> ref int width,
> ref int height )
> {
> Rectangle windowRectangle = new Rectangle();
> GetWindowRect( hWnd, out windowRectangle );
>
> x = windowRectangle.X;
> y = windowRectangle.Y;
> width = windowRectangle.Left - windowRectangle.X;
> height = windowRectangle.Bottom - windowRectangle.X;
> }
>
> public static void SetWindowPosition(
> IntPtr hWnd,
> int x,
> int y,
> int width,
> int height,
> uint uFlags )
> {
> SetWindowPos(
> hWnd,
> (IntPtr)null,
> x, y,
> width, height,
> (uint)uFlags );
> }
> }}
>
> "@ )
>
> $taskbarAutoHide = $false
> $taskbarEdge = 0
> $taskbarX = 0
> $taskbarY = 0
> $taskbarWidth = 0
> $taskbarHeight = 0
>
> # get the taskbar position information
> [Win32Api.WindowSizeUtilities]::GetTaskBarPosition(
> [ref]$taskbarAutoHide,
> [ref]$taskbarEdge,
> [ref]$taskbarX,
> [ref]$taskbarY,
> [ref]$taskbarWidth,
> [ref]$taskbarHeight )
>
> # get the PowerShell window handle
> $powershellHandle = ( Get-Process "powershell" ).MainWindowHandle
>
> $powershellX = 0
> $powershellY = 0
> $powershellWidth = 0
> $powershellHeight = 0
>
> # get the position of the PowerShell window
> [Win32Api.WindowSizeUtilities]::GetWindowPosition(
> $powershellHandle,
> [ref]$powershellX,
> [ref]$powershellY,
> [ref]$powershellWidth,
> [ref]$powershellHeight )
>
> # get the primary monitor information
> $screen = [System.Windows.Forms.Screen]::PrimaryScreen
>
> # work out the new position
> $newX = 0
> $newY = 0
>
> # convert to int for easier comparison
> # Left = 0
> # Top = 1
> # Right = 2
> # Bottom = 3
> $taskbarEdge = [int]$taskbarEdge
>
> if ( !$taskbarAutoHide -and
> ( $taskbarEdge -eq 2 -or $taskbarEdge -eq 3 ) )
> {
> if ( $taskbarEdge -eq 2 )
> {
> $newX = $screen.Bounds.Width -
> $powershellWidth -
> $taskbarWidth
> $newY = $screen.Bounds.Height -
> $powershellHeight
> }
> else
> {
> $newX = $screen.Bounds.Width -
> $powershellWidth
> $newY = $screen.Bounds.Height -
> $powershellHeight -
> $taskbarHeight
> }}
>
> else
> {
> $newX = $screen.Bounds.Width - $powershellWidth
> $newY = $screen.Bounds.Height - $powershellHeight
>
> }
>
> # move the window!
> [Win32Api.WindowSizeUtilities]::SetWindowPosition(
> $powershellHandle,
> $newX,
> $newY,
> -1, # cx
> -1, # cy
> 0x0001 # SWP_NOSIZE - retains the current size -
> # ignores the width and height parameters
> )
>
> Have fun!
>
> Jeff Hillman
One more thing. The following line only works right if you only have
one instance of PowerShell running:

$powershellHandle = ( Get-Process "powershell" ).MainWindowHandle

Jeff
 

My Computer

M

Marco Shaw [MVP]

#4
Marc Scheuner wrote:

> Folks,
>
> Another potentially embarrassing and stupid question: how can I add
> some Powershell magic lines of code to my profile so that the
> PowerShell window appears in the bottom right hand corner of my
> screen? (preferably these lines should be so smart as to deal with
> various screen resolutions, too - on my notebook and my 24" desktop
> screen, for instance).
>
> I looked at various properties of $Host, $Host.UI, $Host.UI.RawUI, but
> couldn't really figure out anything that seemed to make sense......
>
> Thanks for any hints and pointers!
> Marc
If you'd consider adding a snap-in to do this:
http://www.codeplex.com/WASP

Marco

--
Microsoft MVP - Windows PowerShell
http://www.microsoft.com/mvp

PowerGadgets MVP
http://www.powergadgets.com/mvp

Blog:
http://marcoshaw.blogspot.com
 

My Computer

M

Marc Scheuner

#5
Hi Jeff,

>I decided to work out a way to do this, but I have to warn you that
>this isn't exactly a simple solution.
Yes, indeed - that's surprisingly complex - hmm.... have I found the
first "spot" in PowerShell where it does not really solve a "common"
problem with a simple one-liner? :-) Is that still the same in V2 ??
If so, maybe the PowerShell team needs to take notice for the v3 time
frame to add some simple PowerShell commands to size and position its
own window on screen! :-)

Thanks for your effort - highly appreciated !
Marc
 

My Computer

K

Karl Prosser[MVP]

#7
Dealing with the console is a complex thing.
Powershell Plus has extended the console significantly with resize,
screenbuffer size, font , transparency, hotkeys etc. IT has exposed also
exposed a lot of that functionality through the $psplus variable where
you as a scripter can change those attributes. If there is a
functionality that we have exposed to the script through the $psplus
variable, we can easily add it.
-Karl

http://www.powershell.com


Marc Scheuner wrote:

> Hi Jeff,
>

>> I decided to work out a way to do this, but I have to warn you that
>> this isn't exactly a simple solution.
>
> Yes, indeed - that's surprisingly complex - hmm.... have I found the
> first "spot" in PowerShell where it does not really solve a "common"
> problem with a simple one-liner? :-) Is that still the same in V2 ??
> If so, maybe the PowerShell team needs to take notice for the v3 time
> frame to add some simple PowerShell commands to size and position its
> own window on screen! :-)
>
> Thanks for your effort - highly appreciated !
> Marc
 

My Computer

Users Who Are Viewing This Thread (Users: 1, Guests: 0)