Windows 10
PowerShell
Major Minor Build Revision
—– —– —– ——–
5 1 15063 1446
Hello,
I’ve been toying with code from Retired Geek’s post to automatically open applications and rearrange them across multiple display monitors. The problem I run into is that it works for certain applications, but not for others. e.g. works for notepad, but not chrome. I’ve found two possible causes online.
1. The Set-WindowsSizePosition.ps1 function was not written to handle process names that have an array of PID’s, such as Chrome and IE. Note: The following answer is not specifically directed at Retired Geek’s code, but similar code. See answer from JosefZ answered May 19 ’18 at 12:24.
https://superuser.com/questions/1324007/setting-window-size-and-position-in-powershell-5-and-6
2. PowerShell ISE is using some other resolution measurement than that of PowerShell CMD. See comment from Retired Geek at 2016-08-03 20:41.
/showthread//176463-Script-to-Open-Multiple-(selected)-files-and-position-them-on-screen?styleid=4
Now, I’m not certain the issue is due to cause #2 because I tried running the code in both PS ISE and PS CMD and I receive the same error when attempting to move a chrome or IE window. Though, perhaps there’s some conversion issue? Here’s the error:
Cannot convert argument "hWnd", with value: "System.Object[]", for "GetWindowRect" to type "System.IntPtr": "Cannot convert the "System.Object[]" value of type "System.Object[]" to type
"System.IntPtr"."
At H:\Enter\ECC\Working\PowerShell Scripts\Set-WindowSizePositionNew.ps1:178 char:9
+ [void] [Win32]::GetWindowRect($h,[ref]$AppWindow)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument
Note: You’ll notice that I had renamed the Set-WindowsSizePosition.ps1 to Set-WindowSizePositionNew.ps1>
Note: There is more to the error. The MoveWindow portion of Set-WindowsSizePosition.ps1 also receives the same error.
I’ve also added to Set-WorkEnv, so that the script automatically detects all the monitors and determines which monitor it references, e.g. TopLeft, TopRight, Primary, BottomLeft, BottomRight. So, all I should have to do is type in the process name in the correct SWSPArgs array.
I’ll try to paste my Set-WorkEnv below. You’ll notice I currently commented out all monitor fields with the exception of region Primary Monitor.
cls
#region Synopsis
<#
Configure a group of program windows into a desired
configuration on the screen or across multiple screens
and opening the program if necessary.
#>
#endregion Synopsis
#region Instructions
#Instr Need Assistance?
<#
If you need assistance please contact CHRIS KLEST ckles@allstate.com
or ask for help on the employee community powershell group at:
https://allconnect.allstate.com/sites/shoptalk-powershell-scripting/default.aspx
#>
#Instr Configuration:
<#
The following command enables scripts to be run from Powershell.
This is required to be run before running the script and
it's duely noted in the configuration section.
Set-ExecutionPolicy -Scope Process -ExecutionPolicy ByPass
Ensure the path, file name, and extention
to the associated function, Set-WindowSizePosition.ps1,
is accurate. Note: Special Format is required:
period space single-quote path file-name extension single-quote
Two optional parameters:
Desktop icon shortcut. If you want to use it ensure the path to
the program and this file are accurate.
Debug file. When enabled is automatically sent to My Documents on the PC.
To enable it, remove the surrounding greater-than, less-than, and hash symbols.
#>
#Instr Applications Objects:
<#
To add an application write the following requirements.
1. Application name verbatim as listed in processes list. After
opening the application, you can find the process name in task manager details
tab.
2. After the application name add an equal sign =
3. Open single quote '
4. Application path, file name and extension.
5. Close single quote '
Note: Not all apps listed in this section will open on run.
They're there for the user-selected apps in the script to reference.
Note: The use of the MSOfficeBase variable to
keep the command lines shorter.
Note: The hash table is here and not in the
function so that you can use different
sets of programs w/o having to change
the code in the function. Just remember
the table MUST be called $AppList
#>
#Instr Monitor Objects
<#
No action is required. This code finds the x and y coordinates of the attached
monitors and assigns them to variables such as $MonitorTopRight to be used in
application-display mapping section.
#>
#Instr cls
# Clears the powershell screen from previous run.
#Instr Application-Display Map
<#
Associates the application process with the x y coordinates of the
attached display. After AppName =, within quotes, type the app name
as found in the Application Objects list. Ensure you're adding the
app name in the correct region, such as TOP-LEFT MONITOR. Add a number
after Delayseconds. This is the amount of seconds required for the
application to open, if not already opened. For example, it may take
Excel 3 seconds to open. After that time, the application window
is moved to the correct monitor. If a monitor is not being used
comment it out by encapsulating it in the following format:
less-than hash
code
greater-than hash
To enable debugging, remove the hash symbol in the below command
in each region of the Application-Display Map section.
Set-WindowSizePosition @SWSPArgs #-Verbose 4>&1 >> "$DebugFile"
#>
#Instr Associated function
<#
#Note: The function used to open and move the app windows,
Set-WindowSizePosition.ps1, is a separate file.
No changes are required there.
#>
#endregion Instructions
#region Configuration
#Mandatory
#Must Run First. Paste below code (without greater-than, less-than and hash symbols)
#into the command line below, press enter, then click yes on the popup.
<#
Set-ExecutionPolicy -Scope Process -ExecutionPolicy ByPass
#>
#Mandatory.
#Location of associated function. See instructions for details.
. 'H:\Enter\ECC\Working\PowerShell Scripts\Set-WindowSizePositionNew.ps1'
#Desktop Shortcut - Optional
#URL can be used to run this script from desktop.
<#
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
-File "C:\Users\ckles\Desktop\Set-WorkEnv TEST.ps1"
#>
#Debug file location - Optional
#See instructions for details.
<#
$DebugFile="$([Environment]::GetFolderPath('MyDocuments'))\WorkEnv.log"
#>
#endregion Configuration
#region Application Objects
#Additinal Applications
<#
HudWpf = 'C:\Users\webcon\Desktop\Hud2004\HudWpf.exe?' #Disp, 1
acsCNTRL = 'C:\Program Files (x86)\Avaya\CMS Supervisor R18\ACSRun.exe' #Disp, 2
iexplore = 'C:\Program Files (x86)\Internet Explorer\iexplore.exe' #Disp, 3, 11, 15
Firefox = 'C:\Users\webcon\AppData\Local\Mozilla Firefox\Firefox.exe' #Disp, 4, 6, (7=9), 14, 16?
dtclient = "C:\Program Files\Dynatrace\Dynatrace Client 7.1 (x64)\dtclient.ext" #Disp, 5
chrome = 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe' #Disp, 8, 9, 12, 13
POWERPNT = ($MSOfficeBase + 'POWERPNT.exe') #Disp, 10
#>
$MSOfficeBase =
'C:\Program Files (x86)\Microsoft Office\root\Office16\'
$AppList = @{
#OUTLOOK = ($MSOfficeBase + 'Outlook.exe')
#EXCEL = ($MSOfficeBase + 'Excel.exe')
#WINWORD = ($MSOfficeBase + 'WINWORD.exe')
#MSACCESS = ($MSOfficeBase + 'MSAccess.exe')
#ONENOTE = ($MSOfficeBase + 'ONENOTE.exe')
#MSPUB = ($MSOfficeBase + 'MSPUB.exe')
#i_view64 = 'C:\Program Files\IrfanView\i_view64.exe'
notepad = 'C:\Users\ckles\Desktop\New Text Document.txt' #Works perfectly
#powershell_ise =
#'C:\Users\ckles\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Windows PowerShell'
#Calculator = 'C:\Windows\System32\' + 'calc.exe'
acsCNTRL = 'C:\Program Files (x86)\Avaya\CMS Supervisor R18\ACSRun.exe' #Disp, 2
#iexplore = 'C:\Program Files\Internet Explorer\iexplore.exe' #Disp, 3, 11, 15 #error
iexplore = 'C:\Program Files (x86)\Internet Explorer\iexplore.exe'
dtclient = "C:\Program Files\Dynatrace\Dynatrace Client 7.1 (x64)\dtclient.exe" #Disp, 5 #Opens, doesn't move
#chrome = 'C:\Users\Public\Desktop\Google Chrome.lnk'
chrome = 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe' #Disp, 8, 9, 12, 13 #Error
POWERPNT = ($MSOfficeBase + 'POWERPNT.exe') #Disp, 10 # Works
}
#endregion Application Objects
#region MonitorObjects
$MonitorALL=([System.Windows.Forms.Screen]::AllScreens | select -expandproperty workingarea)
For([int]$MonitorNum=0; $MonitorNum -le $MonitorALL.Count -1; $MonitorNum++)
{
$Temp = switch ($true)
{
((($MonitorALL[$MonitorNum] | Select -ExpandProperty "X") -lt 0) -and ($MonitorALL[$MonitorNum] | Select -ExpandProperty "Y") -lt 0){($MonitorTopLeft=($MonitorNum))}
((($MonitorALL[$MonitorNum] | Select -ExpandProperty "X") -gt 0) -and ($MonitorALL[$MonitorNum] | Select -ExpandProperty "Y") -lt 0){($MonitorTopRight=($MonitorNum))}
((($MonitorALL[$MonitorNum] | Select -ExpandProperty "X") -eq 0) -and ($MonitorALL[$MonitorNum] | Select -ExpandProperty "Y") -eq 0){($MonitorPrimary=($MonitorNum))}
((($MonitorALL[$MonitorNum] | Select -ExpandProperty "X") -lt 0) -and ($MonitorALL[$MonitorNum] | Select -ExpandProperty "Y") -gt 0){($MonitorBottomLeft=($MonitorNum))}
((($MonitorALL[$MonitorNum] | Select -ExpandProperty "X") -gt 0) -and ($MonitorALL[$MonitorNum] | Select -ExpandProperty "Y") -gt 0){($MonitorBottomRight=($MonitorNum))}
((($MonitorALL[$MonitorNum] | Select -ExpandProperty "X") -eq $null) -or ($MonitorALL[$MonitorNum] | Select -ExpandProperty "Y") -eq $null){"Null"}
}
}
#endregion MonitorObjects
#region Primary Monitor
#NOTE: IN OUR CONFIGURATION THIS IS ALSO THE TOP-LEFT MONITOR
$SWSPArgs = @{
AppName = 'chrome'
AppWindWidth = ($MonitorALL[$MonitorPrimary] | foreach{$_.Width})
AppWindHeight = ($MonitorALL[$MonitorPrimary] | foreach{$_.Height})
AppWindLeft = ($MonitorALL[$MonitorPrimary] | foreach{$_.Left})
AppWindTop = ($MonitorALL[$MonitorPrimary] | foreach{$_.Top})
DelaySeconds = 5
}
Set-WindowSizePositionNew @SWSPArgs #-Verbose 4>&1 >> "$DebugFile"
#endregion Primary Monitor
#region TOP-LEFT MONITOR
<#
$SWSPArgs = @{AppName = "notepad"
AppWindWidth = ($MonitorALL[$MonitorTopLeft] | foreach{$_.Width})
AppWindHeight = ($MonitorALL[$MonitorTopLeft] | foreach{$_.Height})
AppWindLeft = ($MonitorALL[$MonitorTopLeft] | foreach{$_.Left})
AppWindTop = ($MonitorALL[$MonitorTopLeft] | foreach{$_.Top})
DelaySeconds = 5
#Passthru = $False
}
Set-WindowSizePositionNew @SWSPArgs #-Verbose 4>&1 >> "$DebugFile"
#>
#endregion TOP-LEFT MONITOR
#region TOP-RIGHT MONITOR
<#
$SWSPArgs = @{AppName = "iexplore"
AppWindWidth = ($MonitorALL[$MonitorTopRight] | foreach{$_.Width})
AppWindHeight = ($MonitorALL[$MonitorTopRight] | foreach{$_.Height})
AppWindLeft = ($MonitorALL[$MonitorTopRight] | foreach{$_.Left})
AppWindTop = ($MonitorALL[$MonitorTopRight] | foreach{$_.Top})
DelaySeconds = 5
#Passthru = $False
}
Set-WindowSizePositionNew @SWSPArgs #-Verbose 4>&1 >> "$DebugFile"
#>
#endregion TOP-RIGHT MONITOR
#region BOTTOM-LEFT MONITOR
<#
$SWSPArgs = @{AppName = "iexplore"
AppWindWidth = ($MonitorALL[$MonitorBottomLeft] | foreach{$_.Width})
AppWindHeight = ($MonitorALL[$MonitorBottomLeft] | foreach{$_.Height})
AppWindLeft = ($MonitorALL[$MonitorBottomLeft] | foreach{$_.Left})
AppWindTop = ($MonitorALL[$MonitorBottomLeft] | foreach{$_.Top})
DelaySeconds = 5}
Set-WindowSizePosition @SWSPArgs #-Verbose 4>&1 >> "$DebugFile"
#>
#endregion BOTTOM-LEFT MONITOR
#region BOTTOM-RIGHT MONITOR
<#
$SWSPArgs = @{AppName = "chrome"
AppWindWidth = ($MonitorALL[$MonitorBottomRight] | foreach{$_.Width})
AppWindHeight = ($MonitorALL[$MonitorBottomRight] | foreach{$_.Height})
AppWindLeft = ($MonitorALL[$MonitorBottomRight] | foreach{$_.Left})
AppWindTop = ($MonitorALL[$MonitorBottomRight] | foreach{$_.Top})
DelaySeconds = 5}
Set-WindowSizePosition @SWSPArgs #-Verbose 4>&1 >> "$DebugFile"
#endregion BOTTOM-RIGHT MONITOR
#>
#endregion Application-Display Map
#region Special Thanks
#https://urldefense.proofpoint.com/v2/url?u=https-3A__mcpmag.com_articles_2017_02_02_exploring-2Ddot-2Dsourcing-2Din-2Dpowershell.aspx&d=DwIGAg&c=gtIjdLs6LnStUpy9cTOW9w&r=wT_pfEYup0b8qxyEfMazLAuRdZl1Yty0TWtrVA_8VHM&m=nV4BuYrgddCXv3kD9ZT2uId_xCcEHyD0lVgid2M9K6c&s=HY6xE9wDyQ3QJWSA3yZXyQjNqPLnevRttoy1EY8WJG0&e=
#/showthread//176463-Script-to-Open-Multiple-(selected)-files-and-position-them-on-screen?styleid=4
#Original Programmer : RetiredGeek (WSL) aka: ComputerMentor
#Originally Created : 21 Jul 2016
#Last Updated : By Chris Klest on 1/7/2019
#Current Version 8.0
#endregion Special Thanks