Can a Windows batch file determine the file it opens - windows

I have a file named USER_PREM_HOL_AMT.bat.
The code inside is:
set datename=%date% %username% %~n0
:CheckOS
IF EXIST "C:\Program Files\Microsoft Office\Office14\EXCEL.exe" (GOTO OFFICE2010) ELSE (GOTO OFFICE2013)
:OFFICE2010
ECHO %datename%>>"O:\Holiday.log"
START "" "C:\Program Files\Microsoft Office\Office14\EXCEL.exe" /e "file://///Log_files\Holiday.xlsm"
EXIT
GOTO END
This currently gives the log:
Tue 09/11/2018 7098703 USER_PREM_HOL_AMT
I want it to give me
Tue 09/11/2018 7098703 Holiday.xlsm
Is there a way to do this? Get the file name it's opening instead of its own name.

You can change the first line to specify the filename.
set "datename=%date% %username% Holiday.xlsm"

Related

Reuse result of "where" command

I need to find the specific location of java 64-bit on a windows machine. I thought about using where java to find all possible locations. In the next step I would need to isolate the proper location which starts with: C:\Program Files\Java\... and then execute the command as following:
cmd /K %var% -jar %~dp0XYZ.jar
Is this the proper way to find the java path which might change over time? If yes, how can I get the path from where into a variable?
For the output of where assume this:
C:\Program Files (x86)\Common Files\Oracle\Java\javapath\java.exe
C:\Program Files\Java\jdk1.8.0_144\bin\java.exe
C:\Program Files\Java\jdk1.8.0_144\jre\bin\java.exe
It wouldn't matter if it takes second or third result, as both are 64 bit in this case. But as I can't guarantee that output, the only way to identify the 64-bit version is with C:\Program Files\Java\
The following bat script (commented for explanation) should do the trick:
#ECHO OFF
rem SETLOCAL EnableExtensions DisableDelayedExpansion
set "_flagexe64=:\Program Files\Java\"
set "_javaexe64="
for /f "delims=" %%G in ('where java.exe') do (
rem next two lines for debugging only
echo checking "%%~G"
"%%~G" -version
if not defined _javaexe64 (
set "_javaexe64=%%~G"
call :check64
)
)
rem final check
if not defined _javaexe64 (
1>&2 echo sorry, no java.exe found under "%_flagexe64%"
goto :eof
)
rem java.exe found:
echo "%_javaexe64%"
goto :eof
:check64
call set "_aux=%%_javaexe64:%_flagexe64%=%%"
if "%_aux%" == "%_javaexe64%" set "_javaexe64="
goto :eof

autocomplete path in cmd batch

Windows CMD prompt's auto-complete, (similar feature in other terminals), comes very handy sometimes when you are not sure of the right path or file name.
Bottom line is, how to use this feature in batch scripting.
Example: the script "C:\Program Files\Java\jre1.8.0_92\bin\javaw.exe" -jar post.jar
the thing here is that java version is not always the same, so it needed to be something like this
"C:\Program Files\Java\jre*\bin\javaw.exe" -jar post.jar
you can't use wildcards in the middle of a path, but you can at the end (the last element). Because you need it in between, split it up:
for /f "delims=" %%a in ('dir /b /ad /on "C:\Program Files\Java\jre*"') do set ver=%%a
set "exec=C:\Program Files\Java\%ver%\javaw.exe"
"%exec%" -jar post.jar
This will get you the path with the highest version number, if there are more than one.
Wildcards are supported by only some commands. Moreover, cmd restricts wildcards in a file path only in a path leaf i.e. in token behind last backslash…
On an unknown Windows system: if you do not have control on environment variables then you need to find a file path e.g. as follows (note the _checkPath variable assignment is changed to get reasonable output as I do not have java installed):
#ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
rem assign path with a wildcard * not in path leaf
set "_checkPath=C:\Program Files\Java\jre*\bin\javaw.exe"
rem delete or comment-up next line i.e. my test data set "_checkPath=..."
set "_checkPath=%ProgramFiles%*\Microsoft SQL Server\1*\LocalDB\Binn\sqlservr%1.exe"
set "_itemFirst="
rem previous line: delete variable; next line: show setting
set _checkPath
echo(---
rem next two lines: ensure that a wildcard * not in path leaf is not allowed
echo dir /B /S "%_checkPath%"
dir /B /S "%_checkPath%"
echo(---
rem find all files by parsing powershell output ( note proper escaping ^^^| )
for /F "usebackq tokens= 1* delims=: " %%G in (`
powershell -C Get-ChildItem '"%_checkPath%"' -Recurse ^^^| Format-List -Property FullName
`) do (
rem assign first found item
if not defined _itemFirst set "_itemFirst=%%~H"
rem assign every found item thus last found item
set "_item_Last=%%~H"
rem show every found item
echo .exe found %%~H
)
echo(---
rem show setting found
set _item
echo(---
if defined _itemFirst (
echo success: "%_checkPath%"
rem commands are merely ECHOed and (my test data) commented up
rem use found items (choose any)
rem ECHO "%_itemFirst%" -jar post.jar
rem ECHO "%_item_Last%" -jar post.jar
) else (
echo NOT FOUND "%_checkPath%"
)
Above code snippet is richly commented where necessary for better understanding. Output shows both variants:
==> D:\bat\SO\38281447.bat XXX
_checkPath=C:\Program Files*\Microsoft SQL Server\1*\LocalDB\Binn\sqlservrXXX.exe
---
dir /B /S "C:\Program Files*\Microsoft SQL Server\1*\LocalDB\Binn\sqlservrXXX.exe"
The filename, directory name or volume label syntax is incorrect.
---
---
Environment variable _item not defined
---
NOT FOUND "C:\Program Files*\Microsoft SQL Server\1*\LocalDB\Binn\sqlservrXXX.exe"
==> D:\bat\SO\38281447.bat
_checkPath=C:\Program Files*\Microsoft SQL Server\1*\LocalDB\Binn\sqlservr.exe
---
dir /B /S "C:\Program Files*\Microsoft SQL Server\1*\LocalDB\Binn\sqlservr.exe"
The filename, directory name or volume label syntax is incorrect.
---
.exe found C:\Program Files\Microsoft SQL Server\100\LocalDB\Binn\sqlservr.exe
.exe found C:\Program Files\Microsoft SQL Server\110\LocalDB\Binn\sqlservr.exe
.exe found C:\Program Files\Microsoft SQL Server\120\LocalDB\Binn\sqlservr.exe
---
_itemFirst=C:\Program Files\Microsoft SQL Server\100\LocalDB\Binn\sqlservr.exe
_item_Last=C:\Program Files\Microsoft SQL Server\120\LocalDB\Binn\sqlservr.exe
---
success: "C:\Program Files*\Microsoft SQL Server\1*\LocalDB\Binn\sqlservr.exe"
==>

Windows: start a file using a (non-default) shell verb like "edit" from .bat or command-line

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........

How to check the result of an overwrite file request in Windows CMD?

I have searched online for this, but can't seem to find an answer. I have code that creates a text file after asking one what name he/she would like to give the text file. The file is then opened after being created. However, if I choose N (No) to an overwrite request, I don't want the file to open. I would instead want to be asked again to specify another file name after saying N (No) to the overwrite request.
I however have no idea as to how to check the answer given to the overwrite request.
Also, I would need the entire code to be in one line.
This is what I have without the extras that I am mentioned above:
cmd /c #ECHO OFF & SET /P filename=What File name: & cmd /v /c copy /-y NUL !filename!.txt & cmd start /v /c start notepad !filename!.txt & Exit
Later Added:
I am working on the following and keep getting the error message "( was unexpected at this time." after the filename is echoed. If I edit the file by commenting parts out so that it works, and then continue to edit it to what I currently have, it still works. However, if I exit the cmd box, and then start it again, then it doesn't work and I get an error message. This is the code thus far:
#echo off
SET /P filename=What File name?
echo %filename%
::loop
if exist !filename!.txt (
echo File Exists
SET /P overwrite=Overwrite File?
echo overwrite is %overwrite%
If %overwrite%==Y (
echo "Yes, Y"
)
)
echo finish
If I put single quotes around %overwrite% in If '%overwrite%'==Y I no longer get the unexpected error message. The problem I still face though is when exiting the session / the cmd box, I can't get the line above to echo the value of overwrite. It just says "overwrite is" (without quotes and with no value after it). If I continue in the same session running the batch file over again, I get a value for overwrite.
Solution to unable to echo value of %overwrite% (user input) from if statement can be found here.
edited to adapt to comments
cmd /v:on /q /c "for /l %a in (0 0 1) do (set /p "file=file? " & if exist "!file!" ( set "q=" & set /p "q=overwrite? " & if /i "!q!"=="y" ( type nul > "!file!" & start "" notepad "!file!" & exit ) ) else ( type nul > "!file!" & start "" notepad "!file!" & exit ))"
As requested, in one line. To include it inside a batch file, replace %a with %%a
edited one line, with input validations and error checks added on file operations, and shortened (variables length reduced, unneeded spaces removed, file creation code deduplicated, ...) to fit into windows "Run" dialog
edited added initial cd /d "%userprofile%" to ensure the working folder is writeable. Why? Because from windows 7, including the /v:on (or off) in the call to cmd from the windows Run dialog (the OP reason for a one liner), the active directory for the command is c:\windows\system32 (or wherever the system is). Without the /v switch, the active directory is the user profile folder.
cmd /v:on /q /c "cd/d "%userprofile%"&for /l %a in () do ((set/p"f=file? "||set "f=")&(if defined f if exist "!f!" ((set/p"q=overwrite? "||set "q=0")&if /i not "!q!"=="y" (set "f=")))&if defined f (type nul>"!f!" &&(start "" notepad "!f!" &exit)))"
edited After a lot of tests i make it fail in XP. The previous code will fail if the machine is configured with command extensions disabled. Also, the problem with Ctrl-C can be anoying. This should handle the first problem and minimize the second.
cmd /v:on /e:on /q /c "cd/d "%userprofile%"&for /l %a in ()do ((set/p"f=file? "||(set f=&cd.))&(if defined f if exist "!f!" ((set/p"q=overwrite? "||(set q=&cd.))&if /i not "!q!"=="y" (set f=)))&if defined f (cd.>"!f!"&&(start "" notepad "!f!" &exit)))"
It is better to avoid overwriting by copy in this case (because it's ERRORLEVEL ignores overwriting status). You can do everything on your side:
You can check existance of file (IF EXISTS !filename!.txt),
If file exists, you can ask user what to do (SET /P userInput=Overwrite? (Yes/No/All)),
After it you can analyzed %userInput% to decide what to do (delete existent file and create empty one with the same name + open editor or ask file name again).
If %overwrite%==Y : if %overwrite% is empty, this is executed as If ==Y - obviously a syntax error.
With the singlequoutes you mentioned: If '%overwrite%'==Y is executed as If ''==Y - this is proper syntax, so your code doesn' fail (but is not running as intended)
The reason why %overwrite% is empty: you are using it inside a block (between if ( and the corresponding ), so for parsing reason it' easy (search for delayed expansion).
You can easily avoid that:
#echo off
SET /P filename=What File name?
echo %filename%
:loop
if not exist %filename%.txt goto finish
echo File Exists
SET /P overwrite=Overwrite File?
echo overwrite is %overwrite%
If "%overwrite%"=="Y" ( echo "Yes, Y" ) else ( goto loop )
this line is never reached
:finish
echo finish
When using a single line you can't loop back to the start - but this will only create the file AND start notepad with the file, if the file does not exist.
If the file exists it will just exit and NOT start notepad so you know that you have to try again.
cmd /c #ECHO OFF & SET /P filename=What File name: & cmd /v /c "if not exist !filename!.txt copy NUL !filename!.txt & start "" notepad !filename!.txt" & Exit

Print request upon new file in folder

I've got the following problem:
I need to make something that checks to see whether a file has been added to a specific folder, ifso this file needs to be printed. I heard Windows maybe has something similar built in?
*Program constantly checks whether a file has been added*
File has been added
File gets printed immediately
I have found solutions, but you need to pay for them.
UPDATE
"Code supplied by Vik"
:start
set SECONDS=60
SET FILENAME=*.jpg
IF EXIST %FILENAME% MSPAINT /p %FILENAME%
choice /C a /T %SECONDS% /D a
DEL /Q %FILENAME%
goto :start
"Edits: COPY *.JPG file to a different folder (E.G. ImageHistory)"
"Edits: DELETE local *.JPG file leaving the monitor folder empty"
Any tips or help are welcome!
This batch file will check if the file printme.jpg exists every 60 seconds. If it exists, it will use the built-in MSPAINT program to print it. Feel free to configure SECONDS and FILENAME to suit your environment.
:start
set SECONDS=60
SET FILENAME=printme.jpg
IF EXIST %FILENAME% MSPAINT /p %FILENAME%
choice /C a /T %SECONDS% /D a
goto :start
Additional mods you may want to make:
If you are using an older version of Windows like XP, you may not have the CHOICE command. In that case, use ping to simulate sleeping: PING 1.1.1.1 -n 1 -w 60000 >NUL
You can add a line to delete the file after it's printed: DEL /Q %FILENAME%
EDIT (Below): Added multi-file, move and delete capability
set SECONDS=20
set FILEFOLDER=C:\dropfolder
set TEMPFOLDER=%FILEFOLDER%\TEMPFOLDER
set FILEWILDCARD=*.jpg
if not exist "%FILEFOLDER%" ECHO %FILEFOLDER% NOT FOUND ... CTRL-C TO EXIT && PAUSE
if not exist "%TEMPFOLDER%" ECHO %TEMPFOLDER% NOT FOUND ... CTRL-C TO EXIT && PAUSE
:start
cd "%FILEFOLDER%"
dir /b "%FILEWILDCARD%" > filelist.txt
for %%A in (filelist.txt) do if not %%~zA==0 goto printfiles
choice /C a /T %SECONDS% /D a
goto :start
:printfiles
echo FILE(s) FOUND!
del /q "%TEMPFOLDER%\%FILEWILDCARD%"
move "%FILEWILDCARD%" "%TEMPFOLDER%"
cd "%TEMPFOLDER%"
for %%A in ("%FILEWILDCARD%") do MSPAINT /p "%%A"
goto :start
Run a VB.Net in Background and use a FileSystemWatcher to get events for each change in that folder. Upon receiving an event, check the file / action and print the file using whatever App that can print them. A Batch file will likely not work here.

Resources