How can I output each command lines to one single file but keep monitoring the results at the same command.
#echo off
Title %~n0
if not "%1" == "max" start /MAX cmd /c %0 max & exit/b
Echo Hard Disk Info
set record="C:\%computername%.txt"
Echo.
powershell "get-physicaldisk">C:\%computername%.txt>con
echo=================================
Echo.
Echo CPU Info
Echo.
wmic cpu get caption, name
echo=================================
Echo.
Echo RAM Info
Echo.
wmic memorychip get capacity,memorytype,speed,typedetail,manufacturer
echo=================================
echo.
Echo Windows Version
Echo.
systeminfo | findstr /B /i /C:"OS Name" /C:"OS Version" /C:"System Type" /C:"System Locale" /C:"Input Locale"
echo=================================
Echo.
Echo Office Version
echo.
Echo LCID = 1033-English(US)
wmic product where "Name like '%%Office%%'" get language,name, version
Pause
#exit %0
The following code could be used to write everything into a file and display also in the console window:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
title %~n0
if not "%~1" == "max" start /MAX %SystemRoot%\System32\cmd.exe /D /C %0 max & exit /B
set "RecordFile=%UserProfile%\%ComputerName%.txt"
del "%RecordFile%" 2>nul
set "TempFile=%TEMP%\%~n0.tmp"
call :OutputInfo "Hard Disk Info"
call :OutputData %SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe "Get-PhysicalDisk"
call :OutputInfo "CPU Info"
call :OutputData %SystemRoot%\System32\wbem\wmic.exe CPU GET Caption,Name
call :OutputInfo "RAM Info"
call :OutputData %SystemRoot%\System32\wbem\wmic.exe MEMORYCHIP GET Capacity,MemoryType,Speed,TypeDetail,Manufacturer
call :OutputInfo "Windows Version"
call :OutputData %SystemRoot%\System32\cmd.exe /D /S /C "%SystemRoot%\System32\systeminfo.exe 2>nul | %SystemRoot%\System32\findstr.exe /B /I /C:"OS Name" /C:"OS Version" /C:"System Type" /C:"System Locale" /C:"Input Locale""
call :OutputInfo "Microsoft Office Version"
echo LCID 1033 = English (US)>>"%RecordFile%"
echo LCID 1033 = English (US)
call :OutputData %SystemRoot%\System32\wbem\wmic.exe PRODUCT where "Name like '%%%%Microsoft Office%%%%'" GET Language,Name,Version
del "%TempFile%" 2>nul
echo/
pause
exit /B
:OutputData
%* >"%TempFile%"
for %%I in ("%TempFile%") do if %%~zI == 0 goto :EOF
type "%TempFile%">>"%RecordFile%"
type "%TempFile%"
goto :EOF
:OutputInfo
if not exist "%RecordFile%" goto InfoOutput
(echo =================================& echo/)>>"%RecordFile%"
echo =================================
echo/
:InfoOutput
(echo %~1&echo/)>>"%RecordFile%"
echo %~1
echo/
goto :EOF
Note 1:
The PowerShell command line outputs on Windows 7 with by default installed PowerShell 2.0 just the following error message because of the cmdlet Get-PhysicalDisk is not available with PowerShell 2.0.
The term 'Get-PhysicalDisk' is not recognized as the name of a cmdlet, function,
script file, or operable program. Check the spelling of the name, or if a path
was included, verify that the path is correct and try again.
At line:1 char:17
+ Get-PhysicalDisk <<<<
+ CategoryInfo : ObjectNotFound: (Get-PhysicalDisk:String) [], Co
mmandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Note 2:
WMIC outputs data always Unicode encoded using UTF-16 Little Endian (two or four bytes per character) with byte order mark (BOM) while PowerShell and SystemInfo output data with just one byte per character. For that reason it is not advisable to directly output all data into one text file because of that would result in a text file using more than one character encoding making the file unreadable. Therefore each data output is first written into a temporary file always created new. The temporary file content is output next with command TYPE and the one byte per character encoded output is appended to the record file.
Note 3:
It is necessary to escape both % around Microsoft Office with three additional percent signs to pass %Microsoft Office% to wmic.exe executed in subroutine OutputData. Each % must be escaped with one more % to be interpreted as literal character in a batch file. But a command line with CALL is processed a second time by the Windows command processor. Therefore two more percent signs are necessary on both sides to get first %%Microsoft Office%% after first parsing of the command line and next %Microsoft Office% after the second parsing caused by command CALL.
Note 4:
The usage of just %Office% instead of %Microsoft Office% could result in output not really wanted like:
0 Microsoft Visual Studio 2010 Tools for Office Runtime (x64) 10.0.50908
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
cmd /?
del /?
echo /?
exit /?
for /?
goto /?
if /?
pause /?
powershell get-help get-physicaldisk
set /?
start /?
systeminfo /?
title /?
type /?
wmic /?
wmic cpu /?
wmic cpu get /? and Win32_Processor class
wmic memorychip /?
wmic memorychip get /? and Win32_PhysicalMemory class
wmic product /?
wmic product get /? and Win32_Product class
See also:
Microsoft documentation about Using command redirection operators
DosTips forum topic: ECHO. FAILS to give text or blank line - Instead use ECHO/
How does the Windows Command Interpreter (CMD.EXE) parse scripts?
Single line with multiple commands using Windows batch file
There are very efficient small utilities such as windows versions of Tee or Tail that can help greatly in such situations. However, in the spirit of going commando one possibility is to wrap your existing batch file in a Power Shell emulation of Tee.
On Windows 7 I had a slight hiccup with your cmd file as get-physicaldisk is not recognized but it did not stall the output too much. See #mofi s Note 1.
Also note your end pause was not visible (due to this method of nesting) so I found replacing pause with
echo Press any key to exit & Pause>nul
worked better for me. Also your max option seems to be backwards since without max I get a larger output!
Anyway, assuming your cmd is "monitor.cmd" the following worked as slowly as expected.
powershell.exe -C "& {cmd /c 'monitor max' | tee -filepath monitor.log}"
to review output you can use
type monitor.log
Related
The command I am executing is the following:
dir >> dir.txt
I would be interested in redirecting only certain lines to the txt, for example the last two lines. How can I do that? It occurs to me with findstr, but I don't know how.
A simple findstr match will isolate those two lines based upon them being the only two lines beginning with two spaces:
Dir | FindStr /BC:" " >> "dir.txt"
Assuming that you are under Windows, you can use the Win32 port of the Unix tail command from https://sourceforge.net/projects/tailforwin32/ and then issue the piped command:
dir | tail --lines=2
This shows the last 2 lines
Hope this helps
This can easily be done with PowerShell that you already have on your machine.
powershell -NoLogo -NoProfile -Command "& cmd.exe /C dir | Select-Object -Last 2 | Out-File -FilePath '.\dir.txt' -Encoding ascii -Append"
Alternatively...
powershell -NoLogo -NoProfile -Command "& cmd.exe /C dir | Select-Object -Last 2" >>dir.txt
Here is a simple batch file to get output the last two lines of standard output of command dir with language dependent information about
number of files in directory,
total number of bytes of the files in directory,
number of subdirectories in directory,
free space on partition in bytes.
dir excludes by default directories and files with hidden attribute set because of using implicit /A-H if dir option /A is not used at all.
Here is the batch file to get displayed the last two lines of output of dir executed without any parameters on current directory which of course can be different to directory containing the batch file.
#echo off
setlocal EnableExtensions EnableDelayedExpansion
set "SummaryFiles="
set "SummaryFolders="
for /F delims^=^ eol^= %%I in ('dir') do (
set "SummaryFiles=!SummaryFolders!"
set "SummaryFolders=%%I"
)
if defined SummaryFiles echo !SummaryFiles!
if defined SummaryFolders echo !SummaryFolders!
pause
endlocal
The output done by the two echo can be also redirected into a text file using for example
( if defined SummaryFiles echo !SummaryFiles!
if defined SummaryFolders echo !SummaryFolders!
) >DirectorySummary.txt
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
dir /?
echo /?
endlocal /?
for /?
if /?
pause /?
set /?
setlocal /?
I have a Windows batch file whose purpose is to set some environment variables, e.g.
=== MyFile.cmd ===
SET MyEnvVariable=MyValue
Users can run this prior to doing work that needs the environment variable, e.g.:
C:\> MyFile.cmd
C:\> echo "%MyEnvVariable%" <-- outputs "MyValue"
C:\> ... do work that needs the environment variable
This is roughly equivalent to the "Developer command prompt" shortcuts installed by Visual Studio, which set environment variables needed to run VS utilities.
However if a user happens to have a Powershell prompt open, the environment variable is of course not propagated back to Powershell:
PS C:\> MyFile.cmd
PS C:\> Write-Output "${env:MyEnvVariable}" # Outputs an empty string
This can be confusing for users who switch between CMD and PowerShell.
Is there a way I can detect in my batch file MyFile.cmd that it was called from PowerShell, so that I can, for example, display a warning to the user? This needs to be done without any 3rd party utility.
Your own answer is robust and while it is generally slow due to needing to run a PowerShell process, it can be made significantly faster by optimizing the PowerShell command used to determine the calling shell:
#echo off
setlocal
CALL :GETPARENT PARENT
IF /I "%PARENT%" == "powershell" GOTO :ISPOWERSHELL
IF /I "%PARENT%" == "pwsh" GOTO :ISPOWERSHELL
endlocal
echo Not running from Powershell
SET MyEnvVariable=MyValue
GOTO :EOF
:GETPARENT
SET "PSCMD=$ppid=$pid;while($i++ -lt 3 -and ($ppid=(Get-CimInstance Win32_Process -Filter ('ProcessID='+$ppid)).ParentProcessId)) {}; (Get-Process -EA Ignore -ID $ppid).Name"
for /f "tokens=*" %%i in ('powershell -noprofile -command "%PSCMD%"') do SET %1=%%i
GOTO :EOF
:ISPOWERSHELL
echo. >&2
echo ERROR: This batch file may not be run from a PowerShell prompt >&2
echo. >&2
exit /b 1
On my machine, this runs about 3 - 4 times faster (YMMV) - but still takes almost 1 second.
Note that I've added a check for process name pwsh as well, so as to make the solution work with PowerShell Core too.
Much faster alternative - though less robust:
The solution below relies on the following assumption, which is true in a default installation:
Only a system environment variable named PSModulePath is persistently defined in the registry (not also a user-specific one).
The solution relies on detecting the presence of a user-specific path in PSModulePath, which PowerShell automatically adds when it starts.
#echo off
echo %PSModulePath% | findstr %USERPROFILE% >NUL
IF %ERRORLEVEL% EQU 0 goto :ISPOWERSHELL
echo Not running from Powershell
SET MyEnvVariable=MyValue
GOTO :EOF
:ISPOWERSHELL
echo. >&2
echo ERROR: This batch file may not be run from a PowerShell prompt >&2
echo. >&2
exit /b 1
Alternative approach for launching a new cmd.exe console window on demand:
Building on the previous approach, the following variant simply re-invokes the batch file in a new cmd.exe window on detecting that it is being run from PowerShell.
This is not only more convenient for the user, it also mitigates the problem of the solutions above yielding false positives: When run from an interactive cmd.exe session that was launched from PowerShell, the above solutions will refuse to run, even though they should, as PetSerAl points out.
While the solution below also doesn't detect this case per se, it still opens a useable - albeit new - window with the environment variables set.
#echo off
REM # Unless already being reinvoked via cmd.exe, see if the batch
REM # file is being run from PowerShell.
IF NOT %1.==_isNew. echo %PSModulePath% | findstr %USERPROFILE% >NUL
REM # If so, RE-INVOKE this batch file in a NEW cmd.exe console WINDOW.
IF NOT %1.==_isNew. IF %ERRORLEVEL% EQU 0 start "With Environment" "%~f0" _isNew & goto :EOF
echo Running from cmd.exe, setting environment variables...
REM # Set environment variables.
SET MyEnvVariable=MyValue
REM # If the batch file had to be reinvoked because it was run from PowerShell,
REM # but you want the user to retain the PowerShell experience,
REM # restart PowerShell now, after definining the env. variables.
IF %1.==_isNew. powershell.exe
GOTO :EOF
After setting all environment variables, note how the last IF statement, also re-invokes PowerShell, but in the same new window, based on the assumption that the calling user prefers working in PowerShell.
The new PowerShell session will then see newly defined environment variables, though note that you'll need two successive exit calls to close the window.
As Joe Cocker used to say "I get by with a little help from my friends".
In this case from Lieven Keersmaekers, whose comments led me to the following solution:
#echo off
setlocal
CALL :GETPARENT PARENT
IF /I "%PARENT%" == "powershell.exe" GOTO :ISPOWERSHELL
endlocal
echo Not running from Powershell
SET MyEnvVariable=MyValue
GOTO :EOF
:GETPARENT
SET CMD=$processes = gwmi win32_process; $me = $processes ^| where {$_.ProcessId -eq $pid}; $parent = $processes ^| where {$_.ProcessId -eq $me.ParentProcessId} ; $grandParent = $processes ^| where {$_.ProcessId -eq $parent.ParentProcessId}; $greatGrandParent = $processes ^| where {$_.ProcessId -eq $grandParent.ParentProcessId}; Write-Output $greatGrandParent.Name
for /f "tokens=*" %%i in ('powershell -command "%CMD%"') do SET %1=%%i
GOTO :EOF
:ISPOWERSHELL
echo.
echo ERROR: This batch file may not be run from a PowerShell prompt
echo.
cmd /c "exit 1"
GOTO :EOF
I did something like this for Chocolatey's RefreshEnv.cmd script: Make refreshenv.bat error if powershell.exe is being used.
My solution didn't end being used, for unrelated reasons, but it's available in this repo: beatcracker/detect-batch-subshell. Here is copy of it, just in case.
Script that will only run if called directly from interactive command processor session
Script will detect if it's run from non-interactive session (cmd.exe /c detect-batch-subshell.cmd) and show approriate error message.
Non-interactive shell includes PowerShell/PowerShell ISE, Explorer, etc... Basically anything that will try to execute script by running it in the separate cmd.exe instance.
Hovewer, dropping into the cmd.exe session from PowerShell/PowerShell ISE and executing script there will work.
Dependencies
wmic.exe - comes with Windows XP Professional and up.
Example:
Open cmd.exe
Type detect-batch-subshell.cmd
Output:
> detect-batch-subshell.cmd
Running interactively in cmd.exe session.
Example:
Open powershell.exe
Type detect-batch-subshell.cmd
Output:
PS > detect-batch-subshell.cmd
detect-batch-subshell.cmd only works if run directly from cmd.exe!
Code
detect-batch-subshell.cmd
#echo off
setlocal EnableDelayedExpansion
:: Dequote path to command processor and this script path
set ScriptPath=%~0
set CmdPath=%COMSPEC:"=%
:: Get command processor filename and filename with extension
for %%c in (!CmdPath!) do (
set CmdExeName=%%~nxc
set CmdName=%%~nc
)
:: Get this process' PID
:: Adapted from: http://www.dostips.com/forum/viewtopic.php?p=22675#p22675
set "uid="
for /l %%i in (1 1 128) do (
set /a "bit=!random!&1"
set "uid=!uid!!bit!"
)
for /f "tokens=2 delims==" %%i in (
'wmic Process WHERE "Name='!CmdExeName!' AND CommandLine LIKE '%%!uid!%%'" GET ParentProcessID /value'
) do (
rem Get commandline of parent
for /f "tokens=1,2,*" %%j in (
'wmic Process WHERE "Handle='%%i'" GET CommandLine /value'
) do (
rem Strip extra CR's from wmic output
rem http://www.dostips.com/forum/viewtopic.php?t=4266
for /f "delims=" %%x in ("%%l") do (
rem Dequote path to batch file, if any (3rd argument)
set ParentScriptPath=%%x
set ParentScriptPath=!ParentScriptPath:"=!
)
rem Get parent process path
for /f "tokens=2 delims==" %%y in ("%%j") do (
rem Dequote parent path
set ParentPath=%%y
set ParentPath=!ParentPath:"=!
rem Handle different invocations: C:\Windows\system32\cmd.exe , cmd.exe , cmd
for %%p in (!CmdPath! !CmdExeName! !CmdName!) do (
if !ParentPath!==%%p set IsCmdParent=1
)
rem Check if we're running in cmd.exe with /c switch and this script path as argument
if !IsCmdParent!==1 if %%k==/c if "!ParentScriptPath!"=="%ScriptPath%" set IsExternal=1
)
)
)
if !IsExternal!==1 (
echo %~nx0 only works if run directly from !CmdExeName!^^!
exit 1
) else (
echo Running interactively in !CmdExeName! session.
)
endlocal
Like the answer from beatcracker I think it would be better to not take assumptions about the external shell that can be used to launch the batch script, for instance, the issue can also arise when running the batch file through the bash shell.
Because it exclusively uses the native facilities of CMD and has no dependency on any external tool or the WMI, the execution time is very fast.
#echo off
call :IsInvokedInternally && (
echo Script is launched from an interactive CMD shell or from another batch script.
) || (
echo Script is invoked by an external App. [PowerShell, BASH, Explorer, CMD /C, ...]
)
exit /b
:IsInvokedInternally
setlocal EnableDelayedExpansion
:: Getting substrings from the special variable CMDCMDLINE,
:: will modify the actual Command Line value of the CMD Process!
:: So it should be saved in to another variable before applying substring operations.
:: Removing consecutive double quotes eg. %systemRoot%\system32\cmd.exe /c ""script.bat""
set "SavedCmdLine=!cmdcmdline!"
set "SavedCmdLine=!SavedCmdLine:""="!"
set /a "DoLoop=1, IsExternal=0"
set "IsCommand="
for %%A in (!SavedCmdLine!) do if defined DoLoop (
if not defined IsCommand (
REM Searching for /C switch, everything after that, is CMD commands
if /i "%%A"=="/C" (
set "IsCommand=1"
) else if /i "%%A"=="/K" (
REM Invoking the script with /K switch creates an interactive CMD session
REM So it will be considered an internal invocatoin
set "DoLoop="
)
) else (
REM Only check the first command token to see if it references this script
set "DoLoop="
REM Turning delayed expansion off to prevent corruption of file paths
REM which may contain the Exclamation Point (!)
REM It is safe to do a SETLOCAL here because the we have disabled the Loop,
REM and the routine will be terminated afterwards.
setlocal DisableDelayedExpansion
if /i "%%~fA"=="%~f0" (
set "IsExternal=1"
) else if /i "%%~fA"=="%~dpn0" (
set "IsExternal=1"
)
)
)
:: A non-zero ErrorLevel means the script is not launched from within CMD.
exit /b %IsExternal%
It checks the command line that used to launch the CMD shell to tell if script have been launched from within CMD or by an external app using the command line signature /C script.bat which is typically used by non CMD shells to launch batch scripts.
If for any reason the external launch detection needs to bypasses, for instance when manually launching the script with additional commands to take advantage the defined variables, it can done by prepending # to the path of the script in CMD command line:
cmd /c #MyScript.bat & AdditionalCommands
Ok, I've installed Dropbox but it didn't corresponded to what I was looking for so I uninstalled it with Revo Pro.
But, when i open the taskmanager there are still processes related to it running in my computer so I decided to make a batch to look out and delete all files that are related to it.
#echo off
cd c:\
:a
set /p a=Phrase that might be realted to it
for /r %%d IN (*.*) DO (
(
findstr /i /m /c:%a% "%%d"
if "%errorlevel%"=="0" del "%%d"
echo %errorlevel%
)
)
pause
The problem is: when I run findstr using loop even when there is no match for my variable "%a%" in an analized file %errorlevel% returns as 0. But when I use findstr alone and there isn't a match %ERRORLEVEL% returns as 1 and 0 for a match.
If I use it, I'll delete all my PC files haha. What's wrong with the code?
Within a parenthesised series of statements, any %var% is replaced by the value of that variable at the time the verb controlling that statement-sequence (or block) is encountered.
Here, the block is the entire sequence of statements controlled by the for. %errorlevel% is replaced by the status of errorlevel at the time the for is encountered, so probably 0.
If you use
findstr /i /m /c:%a% "%%d"
if not errorlevel 1 del "%%d"
echo %errorlevel%
then the run-time value of errorlevel is used (ie. as it changes through the operation of the loop) and the command means "if errorlevel is not (1 or greater than 1) do this..."
The findstr will set errorlevel to 0 on found, 1 on not found and 2 for file not found(IIRC) so NOT (1 or greater than 1) selects 0 only. Note that in certain esoteric circumstances, errorlevel may become negative, but after a findstr I believe 0..2 is the allowed range.
Not sure what's wrong with the code, but you can probably skip it using the && operand.
findstr /i /m /c:%a% "%%d" && del "%%d" echo %errorlevel%
Thanks to Stephan for correcting the example.
Whenever Windows command interpreter encounters ( being interpreted as begin of a command block, it parses the entire command block up to matching ) marking end of the command block and replaces all %variable% by current value of the variable.
This means in this case that before command FOR is the first time executed, everything from ( after DO up to last ) is processed already with replacing all %variable% references by current value of the appropriate variable. Then the already preprocessed block is executed one (on command IF) or more times (on command FOR).
This behavior can be seen by debugging the batch file. For debugging a batch file first #echo off must be removed or commented out with command REM or changed to #echo on. Then a command prompt window must be opened and the batch file is executed from within this command prompt window by typing its name with full path enclosed in double quotes if path or name contains a space character. The Windows command interpreter shows now all command lines and command blocks after preprocessing before executing and of course the standard messages and the error messages output by the commands or by Windows command interpreter itself in case of a syntax error in batch file.
Opening a command prompt window means running cmd.exe with option /K to Keep window open after execution of a command or a batch script. Double clicking on a batch file starts also cmd.exe for processing the batch file, but with parameter /C to Close the window automatically after batch processing terminated independent on cause - successful finished or an error occurred.
The command prompt window opened before running the batch file remains open after batch processing finished successfully or with an error except the batch file contains command EXIT without parameter /B. So experts in batch code writing test batch files always by running them from within a command prompt window instead of double clicking on them.
Delayed variable expansion is needed for variables set or modified and referenced within same command block as explained by help of command SET output on running in a command prompt window set /?.
#echo off
setlocal EnableDelayedExpansion
cd /D C:\
:a
set /P "a=Phrase that might be realted to it: "
for /r %%d in (*) do (
%SystemRoot%\System32\findstr.exe /i /m /c:"%a%" "%%d"
if "!errorlevel!" == "0" del "%%d" >nul
)
endlocal
But for checking the exit code of a previous command there is also if errorlevel syntax as explained by Microsoft in support article Testing for a Specific Error Level in Batch Files.
#echo off
setlocal EnableDelayedExpansion
cd /D C:\
:a
set /P "a=Phrase that might be realted to it: "
for /r %%d in (*) do (
%SystemRoot%\System32\findstr.exe /i /m /c:"%a%" "%%d" >nul
if not errorlevel 1 del "%%d" >nul
)
endlocal
if errorlevel X tests if exit code of previous command or application when it modifies the errorlevel variable at all is greater or equal X. By using if not errorlevel X the check is if last exit code is lower than X which is here a test if exit code is 0.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
cd /?
del /?
echo /?
for /?
if /?
set /?
And see also
Microsoft's command-line reference
SS64.com - A-Z index of the Windows CMD command line
Microsoft article about Using command redirection operators
Answer on question Single line with multiple commands using Windows batch file
How to set environment variables with spaces?
How can I start a file with an associated non-default command (shell verb) like "edit", "print", ... from command-line or from a .bat script by using standard Windows means.
(Those extra actions which you get offered on top upon right-click on a file in the Windows Explorer.)
Thus getting the effect of
python -c "import os;os.startfile('somepic.png', 'edit')"
(ShellExecuteEx), but without using extra tools like python, powershell, or so.
The START command does not seem to offer that.
As learned from the comments and after further searching: there seems to be no direct command for that task in standard Windows indeed.
However using a VBScript snippet should be highly compatible and have lowest system requirements. (Works on all machines here directly - from XP - unlike JScript)
VBScript has been installed by default in every desktop release of
Microsoft Windows since Windows 98;1 in Windows Server since Windows
NT 4.0 Option Pack;[2] and optionally with Windows CE (depending on
the device it is installed on).
Example script shellexec.vbs :
' shellexec.vbs : starts a file using a (non-default) shell verb like "EDIT"
' Usage: shellexec.vbs FILE VERB
' Example: shellexec.vbs demo.png EDIT
fn = WScript.Arguments(0)
cmd = WScript.Arguments(1)
Wscript.Echo "ShellExecute """ + cmd + """ on " + fn
CreateObject("shell.application").ShellExecute fn, "", "", cmd, 1
Use from command-line or batch-file:
shellexec.vbs demo.png EDIT
or:
cscript.exe //Nologo shellexec.vbs demo.png EDIT
An example to show how to do it with an one-liner:
mshta vbscript:Execute("CreateObject(""shell.application"").ShellExecute""%SystemDrive%\autoexec.bat"","""","""",""edit"",1:close")
It will open the dummy autoexec.bat file with the application defined to edit .bat files (by default, Notepad).
It is possible to do with batch code what is done by command START for default action of opening a file with associated application.
In the commented batch code below the shell verb must be specified in third line being assigned to environment variable ActionCommand.
The name of the file to edit, printto, ... must be specified as first parameter of the batch file.
#echo off
setlocal EnableExtensions EnableDelayedExpansion
set "ActionCommand=edit"
rem Check if batch file was started with name of an existing file.
if "%~1" == "" set "ErrMsg=No file name specified as argument on starting %~nx0" & goto OutputError
if exist "%~1\" set "ErrMsg="%~f1" is a directory and not a file" & goto OutputError
if not exist "%~f1" set "ErrMsg=A file "%~f1" does not exist" & goto OutputError
rem Check if specified file has a file extension. Files starting with . and
rem not containing at least a second . are also files with no file extension.
if "%~n1" == "" set "ErrMsg=File "%~f1" has no file extension" & goto OutputError
if "%~x1" == "" set "ErrMsg=File "%~f1" has no file extension" & goto OutputError
rem On Windows Vista and later REG.EXE outputs without version info for example:
rem HKEY_CLASSES_ROOT\.txt
rem (Default) REG_SZ txtfile
rem There are only spaces used to separate value name, value type and value string.
rem But REG.EXE version 3.0 outputs on Windows XP with version info for example:
rem ! REG.EXE VERSION 3.0
rem
rem HKEY_CLASSES_ROOT\.txt
rem <NO NAME> REG_SZ txtfile
rem NOTE: There are 4 indent spaces and 2 separating tabs in REG 3.0 output line.
rem So either token 2 or token 3 contains value type REG_SZ
rem used to identify the line with the wanted information.
set "TypeToken=2"
rem Get name of registry key associated with extension of specified file.
:GetAssociatedKey
for /F "skip=1 tokens=%TypeToken%*" %%A in ('%SystemRoot%\System32\reg.exe query "HKCR\%~x1" /ve 2^>nul') do (
if "%%A" == "REG_SZ" set "KeyName=%%B" & goto GetCommand
if "%%A" == "NAME>" set "TypeToken=3" & goto GetAssociatedKey
)
set "ErrMsg=No file assocation found for %~x1 in registry" & goto OutputError
:GetCommand
for /F "skip=1 tokens=%TypeToken%*" %%A in ('%SystemRoot%\System32\reg.exe query "HKCR\!KeyName!\shell\%ActionCommand%\command" /ve 2^>nul') do (
if "%%A" == "REG_SZ" set "ActionCommand=%%B" & goto PrepareCommand
if "%%A" == "REG_EXPAND_SZ" set "ActionCommand=%%B" & goto PrepareCommand
)
set "ErrMsg=No edit command found for %~x1 in registry" & goto OutputError
rem Replace "%1" or %1 by full name of specified file in double quotes or
rem append a space and full name of specified file if the command string
rem does not contain "%1" or %1 at all. Then expand the command string.
:PrepareCommand
set "ActionCommand=!ActionCommand:"%%1"="%~f1"!"
set "ActionCommand=!ActionCommand:%%1="%~f1"!"
if "!ActionCommand:%~f1=!" == "!ActionCommand!" set "ActionCommand=!ActionCommand! "%~f1""
call set "ActionCommand=%ActionCommand%"
rem Run the command with current directory set for the application to folder
rem of specified file without checking if the executable file exists at all.
rem Command start displays an error message box which must be confirmed by
rem the user by a click on button OK and outputs the error message also to
rem console if the executable to start could not be found.
start "" /D"%~dp1" %ActionCommand%
endlocal
goto :EOF
:OutputError
echo %~f0
echo.
echo Error: !ErrMsg!.
echo.
echo Press any key to exit batch processing ...
endlocal
pause >nul
This batch file might not work for all possible action commands, but it should work for 99.5% of all edit, printto, ... commands.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
echo /?
endlocal /?
for /?
goto /?
if /?
pause /?
reg query /?
rem /?
set /?
setlocal /?
start /?
Not sure if this is what you are looking for, but using the START command opens the file I want to edit in the default program.
START "" "Mypdf.pdf"
START "" "Myfile.txt"
START "" "Myjpg.jpg"
ETCETERA ETCETERA........
I have several programs I want to uninstall from my computer (Windows 7 64bit).
Is there a batch\script that can help me do it? or I need to do it one by one from Control Panel?
If there isn't for Windows 7, is there something like this in XP?
thanks,
Dor.
There isn't really an uninstall command kind of thing in cmd that I know of. You could however query this reg key
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
(might also need to check HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall if you're on a 64-bit machine)
to find the program you want to uninstall. Each one will have an UninstallString value which will tell you the path to the programs uninstaller file which you can then execute by calling it's full path and filename.
If the uninstaller happens to be an msi you can use
msiexec /uninstall /x to silently uninstall it. This is about as much as you can do with batch I think.
Hope this helps!
to complement Bali's answer, try the following code...
#echo off
for /f "tokens=*" %%a in ('reg query hklm\software\Microsoft\Windows\CurrentVersion\Uninstall\ ^| find /I "%*"') do (
for /f "tokens=1,2,*" %%b in ('reg query "%%a" /v UninstallString ^| find /I "UninstallString"') do (
if /i %%b==UninstallString (
echo %%d
)
)
)
test it carefully. And then remove the echo command.
I wrote this this morning.
#Echo off
Echo This is a batch file uninstallation program.
Echo Run as administrator WMIC will not work.
echo.
Echo The command [wmic product get name] will run.
Echo Looking up all installed programs...
echo.
wmic product get name
echo 1. First program
echo 2. Second program
echo 3. Third program
echo 4. Fourth program
echo 5. Fifth program
echo.
#echo Pick a number:
echo.
choice /c:12345
if "%errorlevel%"=="1" wmic product where name="First program" call uninstall
if "%errorlevel%"=="2" wmic product where name="Second program" call uninstall
if "%errorlevel%"=="3" wmic product where name="Third program" call uninstall
if "%errorlevel%"=="4" wmic product where name="Fourth program" call uninstall
if "%errorlevel%"=="5" wmic product where name="Fifth program" call uninstall
Echo.
Echo.
#echo First method is done. I'll go into the alternate method.
pause
Echo Get user input - program name?
Echo.
Echo This is an alternate method
:input
set INPUT=
set /P INPUT=Uninstall which program?: %=%
if "%INPUT%"=="" goto input
echo Your input was: %INPUT%
echo.
echo.
Echo Uninstalling...
echo The command [wmic product where name="%INPUT%" call uninstall] will run.
wmic product where name="%INPUT%" call uninstall
#echo If there is "no instance" errors, then the program %INPUT% was uninstalled.
pause
Use wmic right from the terminal. You can look at microsoft's documentation to see more usages.
This will be a great starting point:
wmic product where vendor="Autodesk" call uninstall
I use the above line to clean uninstall autodesk products.
if you don't need it to be (command line) batch, then BCUninstaller is great to remove and cleanup many sotfwater at once in Windows : https://sourceforge.net/projects/bulk-crap-uninstaller/