I'm wondering if there is a way to minimize a batch window after it runs a certain command. I already know start /min and tricks to START the window minimized but what about while it's running a loop or timeout?
Let's say:
echo Hello!
timeout /t 100
:COMMAND TO MINIMIZE WINDOW WHILE TIMEOUT IS RUNNING
Right now i'm calling an autoit script in the bat file to hide the window while the command is running with :
WinSetState($application_name, "", #SW_HIDE)
but i'm looking for a pure batch/powershell/vbs solution that can be coded directly in the .bat file.
Thank you for your time!
Use PowerShell's invocation options, executing no command or script.
#echo off & setlocal
echo Hello!
powershell -window minimized -command ""
timeout /t 100
powershell -window normal -command ""
FWIW, -window hidden is also available if you wish.
You can also minimize all windows by using below code with powershell.
$shell = New-Object -ComObject "Shell.Application"
$shell.minimizeall()
Check:
https://techibee.com/powershell/powershell-minimize-all-windows/1017
You can minimize the command prompt on during the run but you'll need two additional scripts: windowMode and getCmdPid.bat:
#echo off
echo Hello!
call getCmdPid >nul
call windowMode -pid %errorlevel% -mode minimized
timeout /t 100
call getCmdPid >nul
call windowMode -pid %errorlevel% -mode normal
This will do. You need to however run the minimize before the timeout as it is in batch. Timeout will now occur once the window is minimized. This example will keep the window during the ping so you can see it minimizes.
echo Hello!
ping 127.0.0.1
if not DEFINED IS_MINIMIZED set IS_MINIMIZED=1 && start "" /min "%~dpnx0" %* && exit
timeout /t 100
exit
Related
Say my program is as follows
#ECHO Off
start "" "Notepad.exe"
pause
After it opens notepad the windows focus is on notepad so whatever I type is on there, but I want the focus to go back to cmd; is this possible? How?
The specific program i'm trying to run it on, is below:
#ECHO OFF
title SortV8
SETLOCAL ENABLEDELAYEDEXPANSION
cd "C:\img\Unsorted"
:SORT
FOR /R %%f IN (*.jpg *.png *.gif *.jpeg) DO (
echo Current file is: %%f
start "" "D:\Downloads\ImageGlass_Kobe_8.6.7.13_x64\ImageGlass.exe" %%f
powershell.exe -NoProfile -Command "(New-Object -ComObject WScript.Shell).AppActivate((Get-CimInstance Win32_Process -Filter \"ProcessId = $PID\").ParentProcessId)"
CHOICE /N /C 1234 /M "PICK A NUMBER (1 (Photo), 2 (Video), or 3(Delete), 4 (Terminate Program)"%1
IF ERRORLEVEL 4 goto END
IF ERRORLEVEL 3 echo "To the trash it goes!" && move %%f "C:\img\Delete"
IF ERRORLEVEL 2 echo "Video" && move %%f "C:\img\Videos"
IF ERRORLEVEL 1 echo "Photo" && move %%f "C:\img\Photos"
taskkill /IM ImageGlass.exe
cls
GOTO SORT
)
:END
taskkill /IM ImageGlass.exe
cls
echo "Goodbye!"
pause
:eol
You can use PowerShell via its CLI to reactivate your console window, but note that the execution overhead is not insignificant.
Note: This solution is not fully robust, but may work well enough in practice:
#ECHO Off
:: Asynchronously launch Notepad, which steals the focus
:: (Notepad becomes the active window).
start "" "Notepad.exe"
:: Reactivate this console window with the help of PowerShell.
powershell.exe -NoProfile -Command "(New-Object -ComObject WScript.Shell).SendKeys('%%{tab}')"
pause
The above simulates user input, namely an Alt-Tab keypress, in order to reactivate the current console window.
This relies on:
Notepad's window already having been activated (which is likely, given the execution overhead of calling powershell.exe)
the user not manually activating other windows while the batch file runs.
The following variant is more robust, but has a prerequisite that is unlikely to be met:
Rather than sending keystrokes, it properly tries to reactivate the current console window via its process ID.
However, this programmatic window activation only succeeds if the effective SPI_GETFOREGROUNDLOCKTIMEOUT value as reported by the SystemParametersInfo WinAPI function WinAPI function in the current OS uses session is 0, which is not the case by default.
While it is possible in principle to set this value to 0 on demand with PowerShell code, executing such code from cmd.exe (a batch file) inexplicably fails with an Access denied error (whereas direct execution of the same code works fine from PowerShell) - I haven't found a way around this (if someone has an explanation or solution, please tell us).
Certain third-party software - notably AutoHotkey - itself sets the value to 0 once it has run in a session, so if you happen to have a run-on-login AutoHotkey script (it doesn't matter what it does), the code below will work. That said, if you have AutoHotkey already installed, you could try to solve the problem at hand with a specific AutoHotkey script.
#ECHO Off
:: Asynchronously launch Notepad, which steals the focus
:: (Notepad becomes the active window).
start "" "Notepad.exe"
:: !! SEE LIMITATION DISCUSSED ABOVE
:: Reactivate this console window with the help of PowerShell.
powershell.exe -NoProfile -Command "$null = (New-Object -ComObject WScript.Shell).AppActivate((Get-CimInstance Win32_Process -Filter \"ProcessId = $PID\").ParentProcessId)"
pause
I'd like to execute .logopen /u /t /d each time I launch WinDbg - so that a logfile will be created automatically, right from the beginning of each session, without me having to specify it explicitly.
Is there a way to specify a certain command / set of commands to be executed upon WinDbg launch?
You can create a shortcut link or batch file which uses the /c command line parameter:
WinDbg.exe /c ".logopen /t /u /d"
I'm currently trying to run a batch file as a startup script to detect and remove whatever version of office a user has installed and then to install Office 365. I have the install working however, when I attempted to uninstall Office 2013 I received the following error:
Input Error: Can not find script file "C:\Windows\OffScrub_O15msi.vbs"
The Offscrub file is in the same location as the script, is someone able to tell me why it's looking in C:\Windows for it?
Update
Please find my current script which now works for Office 2013, I previously added the line Remove2016Installs $true when using -Command to remove Office 2016, this worked. Since using -File to work around my initial problem I've been unable to get the script to remove Office 2016 and would like some advice on how to do this, I've read that whatever command is after -File needs to be the last which I believe might be why it's failing.
My full script is below:
start "----NOTICE----" cmd.exe /t:ec /Q /k "echo OFFICE 365 IS BEING INSTALLED. THIS WINDOW WILL CLOSE WHEN COMPLETE&&prompt $h"
#echo off
pushd "%~dp0"
powershell.exe -executionpolicy bypass -NoExit -File "Remove-PreviousOfficeInstalls.ps1"
popd
reg Query "HKLM\Hardware\Description\System\CentralProcessor\0" | find /i "x86" > NUL && set OS=32BIT || set OS=64BIT
if %OS%==32BIT "\\domain\SYSVOL\domain\Policies\{Policy Number}\Machine\Scripts\Startup\setup.exe" /configure "\\domain\SYSVOL\domain\Policies\{Policy Number}\Machine\Scripts\Startup\configuration-Office365-x86.xml"
if %OS%==64BIT "\\domain\SYSVOL\domain\Policies\{Policy Number}\Machine\Scripts\Startup\setup.exe" /configure "\\domain\SYSVOL\domain\Policies\{Policy Number}\Machine\Scripts\Startup\configuration-Office365-x64.xml"
taskkill /IM cmd.exe /FI "WINDOWTITLE EQ ----NOTICE----"
taskkill /IM cmd.exe /FI "WINDOWTITLE EQ Administrator: ----NOTICE----"
echo %date% %time% Setup ended with error code %errorlevel%. >> %LogLocation%\%computername%.txt
Update Finished
There's a line that calls the Powershell script Remove-PreviousOfficeInstalls, this is a file from GitHub that is very popular for the removal of whichever Office version you have installed.
I can run this command if say I copy these files to the desktop and amend the locations in the scripts, I'm not sure what this reference to C:\Windows is though when run from \domain\SYSVOL\domain\Policies{Policy Number}\Machine\Scripts\Startup\?
If you run a default instances of PowerShell it always starts in a certain directory. It depends on how and who it is started by. For instance an administrative PowerShell usually starts in C:\Windows\System32. If you use any paths that are not absolute they're applied relative to this directory.
To work around this you need to change the directory it's using. For instance by using cd to change the directory. My guess would be that your script Remove-PreviousOfficeInstalls.ps1 contains a relative call to the VBS.
An easy fix would be to run a script block instead of a single command and just cd to \\domain\SYSVOL\domain\Policies\'{Policy Number}'\Machine\Scripts\Startup\ prior to running the ps1.
The PowerShell help you can view by following [this] link or running powershell -h has the following information in regards to using the -Command switch.
...
Script blocks must be enclosed in braces ({}). You can specify a script block only when running PowerShell.exe in PowerShell. If you want to use a script block when running from another shell you must use the format:
"& {}"
...
The other important parameter for your use case is -File.
Runs the specified script in the local scope ("dot-sourced"), so that the functions and variables that the script creates are available in the current session. Enter the script file path and any parameters.
...
Your batch contains the following line:
powershell.exe -executionpolicy bypass -Command "\\domain\SYSVOL\domain\Policies\'{Policy Number}'\Machine\Scripts\Startup\Remove-PreviousOfficeInstalls.ps1 -Remove2016Installs $true"
What you do is run a single command to invoke a script with a parameter. The problems is that said script checks its locations based on certain function and with your invocation that location is wrongly detected.
There are multiple ways to fix this. One would be to change the directory before invoking the script. To do this you'd need to use a script block as the parameter for -Command. An example for this would be:
powershell.exe -Command "& {Write-Output 'Hello'; Write-Output 'World';}"
As you can see there are two independent Write-Output commands being run. You'd change this to a cd \\domain\SYSVOL\domain\Policies\'{Policy Number}'\Machine\Scripts\Startup\ and the invocation of your script. As a bonus you wouldn't need to put the whole path in front of the script anymore.
The other option would be to run powershell -File with your current invocation of the script. That should also mean that the script is read from the file and the corresponding parameters are populated accordingly.
If neither of these options work you will have to check what $PSScriptRoot is being populated with and/or what the return of (Get-Item -Path ".\").FullName is as those are the two commands used to determine the location of the script that's being executed. To do this you could use a script block.
thanks for your help regarding this. My resolution was to use the following bat command:
`start "----NOTICE----" cmd.exe /t:ec /Q /k "echo OFFICE 365 IS BEING INSTALLED. THIS WINDOW WILL CLOSE WHEN COMPLETE&&prompt $h"`
#echo off
pushd "%~dp0"
powershell.exe -executionpolicy bypass -File Remove-PreviousOfficeInstalls.ps1 -Remove2016Installs
popd
reg Query "HKLM\Hardware\Description\System\CentralProcessor\0" | find /i "x86" > NUL && set OS=32BIT || set OS=64BIT
if %OS%==32BIT "\\Server\Folder\Folder\setup.exe" /configure "\\Server\Folder\Folder\configuration-Office365-x86.xml"
if %OS%==64BIT "\\Server\Folder\Folder\setup.exe" /configure "\\Server\Folder\Folder\configuration-Office365-x64.xml"
taskkill /IM cmd.exe /FI "WINDOWTITLE EQ ----NOTICE----"
taskkill /IM cmd.exe /FI "WINDOWTITLE EQ Administrator: ----NOTICE----"
echo %date% %time% Setup ended with error code %errorlevel%. >> %LogLocation%\%computername%.txt
I had to amend the Remove-PreviousOfficeInstalls powershell script to include the switch command:
[Parameter(ValueFromPipelineByPropertyName=$true)]
[switch]$Remove2016Installs = $false,
This then did exactly what I was after, it detected the current version of Office, removed it and installed the correct bit version of Office 365 for that PC\Laptop.
Thanks for all your help
I currently have a .cmd file that runs the following two commands on startup
PowerShell -Command "Set-ExecutionPolicy Unrestricted" >> "%TEMP%\StartupLog.txt" 2>&1
PowerShell C:\Users\elias\Desktop\Script123.ps1 >> "%TEMP%\StartupLog.txt" 2>&1
But when this runs on startup it shows the command prompt. I'm wondering if there's anyway to run this without showing the command prompt.
Thank You
Invoking a .cmd file directly invariably opens a console window, so you need to invoke it via a wrapper executable that hides it:
This answer of mine contains a VBScript script that does just that; assuming you've saved it as runHidden.vbs in the current dir and that you want to invoke some-batch-file.cmd from the current dir:
wscript .\runHidden.vbs cmd "/c .\some-batch-file.cmd"
Try powershell -command "& { $x = New-Object -ComObject Shell.Application; $x.minimizeall() }" in the beginning of the code.
This command can minimize all windows.
I hope this can be helpful, if you have any other questions, please comment below.
Create a wrapper with VBScript:
Option Explicit
Dim WshShell
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run "cmd /c blah.cmd", 0, False
Then change the startup item to
wscript.exe wrapper.vbs
I have following PowerShell script:
cmd /c script1.bat
cmd /c script2.bat
script1.bat at the end of execution have "pause" command, so the execution of my PS script stops.
How can send any key cmd.exe to avoid stopping script execution?
NOTE: I can't change batch scripts - they are 3rd party.
You can pipe input to the program (cmd.exe) like this:
"X" | cmd /c script1.bat
You could put an empty file called pause.bat in the same directory. Then it would do nothing instead of pause.
The batch scripts may be 3rd party, but surely you can just a copy/backup and edit the content to remove the PAUSE command?
I sometimes put a PAUSE in if I am testing something and don't want the window to close, but otherwise I can't think of a good reason to keep that in.
I had trouble getting the accepted answer to work for me due having an expression in the bat file path.
"x" | $Env:WRAPPER_HOME\bat\installService.bat $LOGFILE
Error is "Expressions are only allowed as the first element of a pipeline."
Here's what I got working (finally):
[PS script code]
& runner.bat bat_to_run.bat logfile.txt
[runner.bat]
#echo OFF
REM This script can be executed from within a powershell script so that the bat file
REM passed as %1 will not cause execution to halt if PAUSE is encountered.
REM If {logfile} is included, bat file output will be appended to logfile.
REM
REM Usage:
REM runner.bat [path of bat script to execute] {logfile}
if not [%2] == [] GOTO APPEND_OUTPUT
#echo | call %1
GOTO EXIT
:APPEND_OUTPUT
#echo | call %1 1> %2 2>&1
:EXIT