Reputation: 91
The following .bat file below simply opens two text files overlaying them, but I'm wondering if it's possible to define a specific display source, or if anyone can assist in providing the correct parameters.
@echo off
START /max /wait NOTEPAD.EXE C:\test\screen1.txt
START /max /wait NOTEPAD.EXE C:\test\screen2.txt
What I'm trying to get:
@echo off
START /max /wait NOTEPAD.EXE C:\test\screen1.txt "monitor1"
START /max /wait NOTEPAD.EXE C:\test\screen2.txt "monitor2"
So the results I am trying to receive is that screen1.txt opens on monitor1, and screen2.txt on monitor2.
Upvotes: 9
Views: 34042
Reputation: 11
@ebloch helped me find a solution: -Move the cmd window to the desired location on the screen(s). -Right-click. -Select "Properties". -Select "Layout". -Uncheck box "Let system position window". -Click "OK"
The cmd window now opens in the location I dragged it to automatically when I run the .bat file.
Upvotes: 1
Reputation: 2580
cmdow will do this for you.
I use it but please be aware that AV flags it as a virus. There is an explanation why this is the case given by the author on the github page link above.
Usage
Get a list of all windows & find your window in the list.
cmdow
Move the window.
You need specify the window handle in hex or use the window title.
cmdow "window title" /mov 500 500
Upvotes: 2
Reputation: 24476
Unless the application you're launching has a command-line switch for it, there's no easy way to specify on which monitor to display a window. As far as I'm aware, neither start
nor notepad
supports such a switch. The closest solution I've found is to move a window after it's already open.
Here's a hybrid batch + PowerShell script to launch a program and move it to a specific monitor. Save it with a .bat extension.
<# : batch portion
@echo off & setlocal disabledelayedexpansion
set args=%*
call set args=%%args:%1 %2=%%
set "exe=%~2"
set "monitor=%~1"
set "scriptname=%~nx0"
powershell -noprofile "iex (${%~f0} | out-string)"
exit /b %ERRORLEVEL%
: end batch / begin powershell #>
function usage() {
write-host -nonewline "Usage: "
write-host -f white "$env:scriptname monitor# filename [arguments]`n"
write-host -nonewline "* "
write-host -f white -nonewline "monitor# "
write-host "is a 1-indexed integer. Monitor 1 = 1, monitor 2 = 2, etc."
write-host -nonewline "* "
write-host -f white -nonewline "filename "
write-host "is an executable or a document or media file.`n"
write-host -nonewline "$env:scriptname mimics "
write-host -f white -nonewline "start"
write-host ", searching for filename both in %PATH% and"
write-host "in Windows' app paths (web browsers, media players, etc).`n"
write-host "Examples:"
write-host "To display YouTube in Firefox on your second monitor, do"
write-host -f white " $env:scriptname 2 firefox `"www.youtube.com`"`n"
write-host "To play an mp3 file using the default player on monitor 1:"
write-host -f white " $env:scriptname 1 mp3file.mp3"
exit 1
}
add-type user32_dll @'
[DllImport("user32.dll")]
public static extern void SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter,
int x, int y, int cx, int cy, uint uFlags);
'@ -namespace System
add-type -as System.Windows.Forms
if ($env:monitor -gt [windows.forms.systeminformation]::MonitorCount) {
[int]$monitor = [windows.forms.systeminformation]::MonitorCount
} else {
[int]$monitor = $env:monitor
}
try {
if ($env:args) {
$p = start $env:exe $env:args -passthru
} else {
$p = start $env:exe -passthru
}
}
catch { usage }
$shell = new-object -COM Wscript.Shell
while (-not $shell.AppActivate($p.Id) -and ++$i -lt 100) { sleep -m 50 }
try {
$x = [Windows.Forms.Screen]::AllScreens[--$monitor].Bounds.X
$hwnd = (Get-Process -id $p.Id)[0].MainWindowHandle
[user32_dll]::SetWindowPos($hwnd, [intptr]::Zero, $x, 0, 0, 0, 0x41);
}
finally { exit 0 }
And moving a window is no easy task, either. See this post for some other options. But here's a batch script that will compose and link a C# app on the fly to handle window moves.
@echo off
setlocal
:: // generate c.cs
call :heredoc movewind >"%temp%\c.cs" && goto compile_and_link
// syntax: movewind.exe [pid | "window title"] x y
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
class movewind {
[DllImport("user32.dll", SetLastError = true)]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
static void Main(string[] args) {
int pid;
string title;
bool res = Int32.TryParse(args[0], out pid);
if (res) {title = Process.GetProcessById(pid).MainWindowTitle;} else {title = args[0];}
IntPtr handle = FindWindow(null, title);
try {
SetWindowPos(handle, IntPtr.Zero, Convert.ToInt32(args[1]), Convert.ToInt32(args[2]), 0, 0, 0x41);
}
catch (Exception e) {
Console.WriteLine("Exception caught while attempting to move window with handle " + handle);
Console.WriteLine(e);
}
}
}
:compile_and_link
set "movewind=%temp%\movewind.exe"
for /f "delims=" %%I in ('dir /b /s "%windir%\microsoft.net\*csc.exe"') do (
if not exist "%movewind%" "%%I" /nologo /out:"%movewind%" "%temp%\c.cs" 2>NUL
)
del "%temp%\c.cs"
if not exist "%movewind%" (
echo Error: Please install .NET 2.0 or newer.
goto :EOF
)
:: // get left monitor width
for /f "tokens=2 delims==" %%I in ('wmic desktopmonitor get screenwidth /format:list') do set "x=%%I"
:: // make sure test environment is in place
if not exist "c:\test" mkdir "c:\test"
if not exist "c:\test\screen1.txt" >"c:\test\screen1.txt" echo This should be on the left.
if not exist "c:\test\screen2.txt" >"c:\test\screen2.txt" echo This should be on the right.
:: // syntax: movewind.exe [pid | "window title"] x y
start /max notepad.exe "c:\test\screen1.txt"
call :movewind "screen1.txt - Notepad" 0 0
start /max notepad.exe "c:\test\screen2.txt"
call :movewind "screen2.txt - Notepad" %x% 0
del "%movewind%"
:: // end main runtime
goto :EOF
:: // SCRIPT FUNCTIONS
:movewind <title> <x> <y>
tasklist /v | find /i "%~1" && (
"%movewind%" "%~1" %~2 %~3
goto :EOF
) || (
ping -n 1 -w 500 169.254.1.1 >NUL
goto movewind
)
:heredoc <uniqueIDX>
:: // https://stackoverflow.com/a/15032476/1683264
setlocal enabledelayedexpansion
set go=
for /f "delims=" %%A in ('findstr /n "^" "%~f0"') do (
set "line=%%A" && set "line=!line:*:=!"
if defined go (if #!line:~1!==#!go::=! (goto :EOF) else echo(!line!)
if "!line:~0,13!"=="call :heredoc" (
for /f "tokens=3 delims=>^ " %%i in ("!line!") do (
if #%%i==#%1 (
for /f "tokens=2 delims=&" %%I in ("!line!") do (
for /f "tokens=2" %%x in ("%%I") do set "go=%%x"
)
)
)
)
)
goto :EOF
Upvotes: 3
Reputation: 13
(Win 7) To specify location to open a CMD window just run the batch or CMD and then position the CMD window where you want it, including on which monitor if you have more than one, and then right click on its title bar, select Properties, and click OK. The next time the CMD window opens using the same batch or icon it will be in the new location.
Upvotes: -5