News, tips, advice, support for Windows, Office, PCs & more. Tech help. No bull. We're community supported by donations from our Plus Members, and proud of it
Home icon Home icon Home icon Email icon RSS icon
  • PowerShell 5, Move/Arrange Active Windows

    Home Forums Developers, developers, developers DevOps Lounge PowerShell 5, Move/Arrange Active Windows

    This topic contains 5 replies, has 2 voices, and was last updated by

     RetiredGeek 2 months ago.

    • Author
      Posts
    • #321335 Reply

      ChrisJ
      AskWoody Lounger

      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.
      http://forums.windowssecrets.com/showthread.php/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=
      
      #http://forums.windowssecrets.com/showthread.php/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
      
    • #321395 Reply

      ChrisJ
      AskWoody Lounger

      Below is the function associated with the above script:

      
      Function Set-WindowSizePositionNew {
      
      #region Synopsis
      
      <#
      
      .Synopsis
      Configure a program window to a specified size and location,
      and opening the program if necessary.
      
      .Description
      Completely configure a program window to a specified size
      (height/width) and positioning that window on a single and/or
      multiple monitor setup at a given x,y coordinate.
      
      .Parameter AppName
      The name of the application. This must be the exact spelling
      as is returned by Get-Process.
      
      .Parameter AppWindWidth
      The desired width of the application window. To place on a
      second screen add the width of the 1st screen.
      Note: Use the Working Resolution of your displays!
      
      .Parameter AppWindHeight
      The desired height of the application window.
      
      .Parameter AppWindLeft
      The position of the left border of the application window.
       
      .Parameter AppWindTop
      The position of the top border the application window.
       
      .Parameter DelaySeconds
      The number of seconds to wait before continuing with the
      program when an application has to be opened. Different
      applications take variable times to start and the program
      can not proceed until the application has been initialized.
      
      .Outputs
      Application opened and window positioned and sized on screen
      
      .Notes
      Programmer   : RetiredGeek (WSL) aka: ComputerMentor
      Created      : 21 Jul 2016
      Last Updated :
      Current Vers : 2.0
      
      .Example
      $SWSPArgs = @{
          AppName       = "Excel"
          AppWindWidth  = [Int]($EffScrnWidth/2)
          AppWindHeight = $EffScrnHeight
          AppWindLeft   = $EffScrnWidth
          AppWindTop    = 0
          DelaySeconds  = 1}
          Set-WindowSizePosition @SWSPArgs
      
      Setup an Excel window on screen 2 of a 2 screen setup at a width of
      1/2 of the screen.
      
      .Example
      $SWSPArgs = @{
          AppName       = "Excel"
          AppWindWidth  = $EffScrnWidth
          AppWindHeight = $EffScrnHeight
          AppWindLeft   = 0
          AppWindTop    = 0
          DelaySeconds  = 1}
      Set-WindowSizePosition @SWSPArgs -Verbose 4>&1 >> "$DebugFile"
      
      Setup Excel with size of $EffScrnWidth and Height of $EffScrnHeight
      located on screen one in upper left corner and if Excel is not
      running wait 1 second before attemption to process. Output actual
      coordinates to the WorkEnv.Log file in the users Documents folder.
      #>
      #endregion Synopsis
       
      #region Instructions
      
      #Run First
      #PowerShell -ExecutionPolicy Bypass -File Set-WorkEnv.ps1
      
      #Adjust the seconds count below based on the  
      #loading speed of your applications on your    
      #computer. Set to time to load the slowest     
      #loading application in the $AppList hashtable.
      
      #endregion Instructions
      
      #region Parameters
      
      Param (
          [Parameter(Mandatory=$True)]
            [String] $AppName,
          [Parameter(Mandatory=$True)]
            [Int] $AppWindWidth,
          [Parameter(Mandatory=$True)]
            [Int] $AppWindHeight,
          [Parameter(Mandatory=$True)]
            [Int] $AppWindLeft,
          [Parameter(Mandatory=$True)]
            [Int] $AppWindTop,
          [Parameter(Mandatory=$False)]
            [Int] $DelaySeconds
      )
      
      #endregion Parameters
      
      #region Special Thanks
      
      # https://urldefense.proofpoint.com/v2/url?u=http-3A__stackoverflow.com_questions_2556872_how-2Dto-2Dset-2Dforeground-2Dwindow-2Dfrom-2Dpowershell-2Devent-2Dsubscriber-2Daction&d=DwIGAg&c=gtIjdLs6LnStUpy9cTOW9w&r=wT_pfEYup0b8qxyEfMazLAuRdZl1Yty0TWtrVA_8VHM&m=nV4BuYrgddCXv3kD9ZT2uId_xCcEHyD0lVgid2M9K6c&s=XTKzbLs4DHSEPCCkKW0gDxLmcYSfmelUFn7LCnFBLXs&e=
      # https://urldefense.proofpoint.com/v2/url?u=http-3A__richardspowershellblog.wordpress.com_2011_07_23_moving-2Dwindows_&d=DwIGAg&c=gtIjdLs6LnStUpy9cTOW9w&r=wT_pfEYup0b8qxyEfMazLAuRdZl1Yty0TWtrVA_8VHM&m=nV4BuYrgddCXv3kD9ZT2uId_xCcEHyD0lVgid2M9K6c&s=5s6I9JxmSZ52gJCkEUallwVqH-EKY6COIWGyDol7EnQ&e=
      # https://urldefense.proofpoint.com/v2/url?u=http-3A__www.suite101.com_content_client-2Darea-2Dsize-2Dwith-2Dmovewindow-2Da17846&d=DwIGAg&c=gtIjdLs6LnStUpy9cTOW9w&r=wT_pfEYup0b8qxyEfMazLAuRdZl1Yty0TWtrVA_8VHM&m=nV4BuYrgddCXv3kD9ZT2uId_xCcEHyD0lVgid2M9K6c&s=UYXhi5a2XMwG2IIaR48Cd8dUmOWERo0HU3Hc4emrHlY&e=
      
      #endregion Special Thanks
         
      #region ADD DLL
      Add-Type @"
      
      using System;
      using System.Runtime.InteropServices;
      
      public class Win32
      {   
          [DllImport("user32.dll")]
          [return: MarshalAs(UnmanagedType.Bool)]
          public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
          
          [DllImport("user32.dll")]
          [return: MarshalAs(UnmanagedType.Bool)]
          public static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);
          
          [DllImport("user32.dll")]
          [return: MarshalAs(UnmanagedType.Bool)]
          public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
      }
      
      public struct RECT
      {
          public int Left;   // x position of upper-left corner
          public int Top;    // y position of upper-left corner
          public int Right;  // x position of lower-right corner
          public int Bottom; // y position of lower-right corner
      }
      "@
      
      #endregion ADD DLL
      
      #region CreateWindowObjects
          $AppWindow  = New-Object RECT
          $ScrnWindow = New-Object RECT
      
      #endregion CreateWindowObjects
          
      #region OpenApplication
          
      $h = (Get-Process | where {$_.ProcessName -eq "$AppName"})
          If ($h -eq $Null){
              &($AppList.$AppName)
      
              If (Test-Path -Path variable:DelaySeconds) 
              {
                  Test-Path -Path variable:DelaySeconds #Chris K, Added 1/22/2019
                  Start-Sleep -Seconds $DelaySeconds
              }
      
              $h = (Get-Process | where {$_.ProcessName -eq "$AppName"})
          }
          
      #endregion OpenApplication
      
      #region MoveWindow
          
      If ($h -ne $null) {
              $h = $h.MainWindowHandle
          
              [void] [Win32]::GetWindowRect($h,[ref]$AppWindow)
              Write-Verbose -Message "$AppName"
              Write-Verbose -Message $(
                  "App : Left $($AppWindow.Left)  Width $($AppWindow.Right) " +
                  "Top $($AppWindow.Top)  Height $($AppWindow.Bottom)")
              Write-Verbose -Message $(
                  "New : Left $($AppWindLeft)  Width $($AppWindWidth) " +
                  "Top $($AppWindTop)  Height $($AppWindHeight)")    
          
              [void] [Win32]::MoveWindow(
                  $h, $AppWindLeft, $AppWindTop,
                  $AppWindWidth, $AppWindHeight, $true 
              )
          }
          
      #endregion MoveWindow
      } #End Function Set-WindowSizePosition
       
      Function Set-WindowStyle {
      
      #region special thanks
      #https://urldefense.proofpoint.com/v2/url?u=https-3A__gist.github.com_jakeballard_11240204&d=DwIGAg&c=gtIjdLs6LnStUpy9cTOW9w&r=wT_pfEYup0b8qxyEfMazLAuRdZl1Yty0TWtrVA_8VHM&m=nV4BuYrgddCXv3kD9ZT2uId_xCcEHyD0lVgid2M9K6c&s=vpT6Uv-fSGOQMSDWkE-mlK-0zYoipRRX72JrnqzAS48&e=
      #endregion special thanks
      
      #region Parameters
      
      [CmdletBinding(DefaultParameterSetName = 'InputObject')]
      
      param(
      
      	[Parameter(Position = 0, Mandatory = $True, ValueFromPipeline = $True, ValueFromPipelinebyPropertyName = $True)]
      	[Object[]] $InputObject,
      	[Parameter(Position = 1)]
      	[ValidateSet('FORCEMINIMIZE', 'HIDE', 'MAXIMIZE', 'MINIMIZE', 'RESTORE', 'SHOW', 'SHOWDEFAULT', 'SHOWMAXIMIZED', 'SHOWMINIMIZED', 'SHOWMINNOACTIVE', 'SHOWNA', 'SHOWNOACTIVATE', 'SHOWNORMAL')]
      	[string] $Style = 'SHOW'
          ) #END param
      
      #endregion Parameters
      
      #region begin
          
      	BEGIN {
              $WindowStates = @{
      
      			'FORCEMINIMIZE'   = 11
                  'HIDE'            = 0
                  'MAXIMIZE'        = 3
                  'MINIMIZE'        = 6
                  'RESTORE'         = 9
                  'SHOW'            = 5
                  'SHOWDEFAULT'     = 10
                  'SHOWMAXIMIZED'   = 3
       			'SHOWMINIMIZED'   = 2
      			'SHOWMINNOACTIVE' = 7
      			'SHOWNA'          = 8
      			'SHOWNOACTIVATE'  = 4
      			'SHOWNORMAL'      = 1
      		}
      		
      #region add-DLL
      	$Win32ShowWindowAsync = Add-Type -MemberDefinition @'
      		[DllImport("user32.dll")]
      		public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
      '@ -Name "Win32ShowWindowAsync" -Namespace Win32Functions -PassThru
      
      #endregion add-DLL
      
      	}#end begin
      
      #endregion begin
      
      #region process  
      
      	PROCESS{
              
      		foreach($process in $InputObject) {
      			 $Win32ShowWindowAsync::ShowWindowAsync(
      
      				$process.MainWindowHandle, $WindowStates[$Style]) | Out-Null
              
      					}
          
      		} #End PROCESS
      
      #endregion process
      
      }#End Function Set-WindowStyle
      
    • #322846 Reply

      RetiredGeek
      AskWoody MVP

      Chris,

      I’m currently traveling and only have a laptop. I’ll look into this problem when I return home in 10 days or so.

      May the Forces of good computing be with you!

      RG

      PowerShell & VBA Rule!
      Computer Specs

    • #327291 Reply

      RetiredGeek
      AskWoody MVP

      Chris,

      Finally got back home and to my computer with multiple screens to test this out.

      It turns out that the problem is not Chrome having multiple processes (I’ve programmed a fix for that) but rather that Chrome is a 64 bit program vs a 32 bit program as are most of the programs I still use (Office, Notepad++, etc).

      32vs64-bit
      Trying to convert a 64 bit value into a 32 bit pointer causes the error.

      Generally, you can’t cross over, you have to use either all 32 bit or all 64 bit items. I’ll see if I can find a solution to this but it will probably take a while.

      FYI: the fix for the multi-process problem (if my logic is correct) is to select the process with the most threads as this, in chrome at least, is the main process. BTW: you can use Shift+Esc in Chrome to show all the process it uses and this is how I found out which process was the one controlling the display. I then matched up the PID with Process Explorer and then determined that it had many more threads than any of the other chrome processes.

      Change Function-Set-WindowSizePosition.ps1 as follows:

        If ($h -ne $null) {
      #-------------------------------------------
          If ($h.count -gt 1) {
            $temp = $h | Sort-Object -Descending -Property Handles
            $h = $y[0]
          } #If ($h.count...
      #-------------------------------------------
          $h = $h.MainWindowHandle
          [void] [Win32]::GetWindowRect($h,[ref]$AppWindow)
      
      

      May the Forces of good computing be with you!

      RG

      PowerShell & VBA Rule!
      Computer Specs

      • This reply was modified 2 months, 1 week ago by
         RetiredGeek.
      • This reply was modified 2 months, 1 week ago by
         RetiredGeek.
      Attachments:
      You must be logged in to view attached files.
      • #329114 Reply

        ChrisJ
        AskWoody Lounger

        Hi RetiredGeek,

        Thanks for researching this. The additional code you provided helps a lot, though, I’ve replaced what I assumed was a typo, $temp instead of $y. Chrome now opens correctly. iexplore, opens, but it doesn’t open in full screen mode. Also, I noticed that if I run the script twice on iexplore that it freezes that window. In an attempt to maximize the iexplore window I’ve re-added the Set-WindowStyle reference back into my code, though, to no avail. What I’m going to try next is perform that same descending sort on the processes in Set-WindowStyle and maximize the [0] process.

        p.s. I’m not sure why the code in my original post has collapsed; I placed the code tags around it.

        Thanks,
        Chris

    • #329145 Reply

      RetiredGeek
      AskWoody MVP

      Chris,

      The code tags don’t work. Use pre tags instead.

      May the Forces of good computing be with you!

      RG

      PowerShell & VBA Rule!
      Computer Specs

    Please follow the -Lounge Rules- no personal attacks, no swearing, and politics/religion are relegated to the Rants forum.

    Reply To: PowerShell 5, Move/Arrange Active Windows

    You can use BBCodes to format your content.
    Your account can't use Advanced BBCodes, they will be stripped before saving.

    Your information:


    Comments are closed.