Sorry about the lousy title, I don't really know how to fit my question into a few words.
This may probably seem trivial to you guys, but I'm trying to automate a task that goes something like this:
Check if a certain executable exists
If it exists, run the executable, which has two possible outcomes:
Update found.
Update not found.
If outcome A, run a certain command. If outcome B, run another command.
The executable gives an output in the command line window, but I'm stranded on how to make the IF command read the output and use it.
English isn't my first language and my vocabulary regarding this is rather limited, so just let me know if something isn't clear.
if exist path\filename.ext anycommand checks, if a file exists and if yes, executes anycommand
anycommand >temp.txt writes the output of a command to a textfile.
set /p variable=<temp.txt writes the content of the textfile to a variable (well, at least the first line)
if "%variable%"=="Update not found" othercommand runs othercommand, if %variable% is equal to "Update not found"
Something along these lines might be what you're looking for: (This is an example, not the exact program)
set file_path=C:\Users\Atyai\Desktop\ExampleFile.bat
if exist %file_path% echo Update Found. && ::Then put your command right here
if not exist %file_path% echo Update Not Found. && ::Put your other command here
What this does, is when the file exists, it echoes "Update found" then I left some room for your second command. In the case that the file does not exist, it echoes "Update Not Found."
The file path I gave you (first line) needs to be replaced with your own.
This might provide some help:
http://ss64.com/nt/if.html
Related
I have a batch file that calls a VB Script file. This VB Script comes from MS Office Suite and is located in the Installed Folder. My file calls the VB Script and pipes it to a file using the > symbol. This works if your redirect is a string. I was wondering how to redirect to a file using a variable.
I'm only including a small fraction of the code showing how I want it to work.
This, as written, works. However I want my batch file to use a variable instead of the text in quotes. In fact, my batch file creates the path depending on where the batch file is located.
::Create file and display on screen
Echo Writing Information to File: "OfficeStatus.txt"
Call cscript ospp.vbs /dstatus > OfficeStatus.txt
Echo.
When written as shown below, it does not work:
::Create file and display on screen
Echo Writing Information to File: "OfficeStatus.txt"
Call cscript ospp.vbs /dstatus > %_sLogFile%
Echo.
I don't know if the issue is because of the redirect not able to handle a variable or not. An example of what might be in the variable:
_sLogFile=E:\UserName\Documents\Status\OfficeStatus.txt.
Any thoughts would be great.
The variable, by the way, correctly contains the path and filename... so that's not the issue.
it does not work means did not do what I expected and unfortunately does not tell us what it did do.
Did it crash the system? Create an error message (If so, what message)? Create an output file in an unexpected place??
Personally, I'd suspect what you have concealed as username. Without knowing precisely what that text is, we start guessing, which isn't a logical approach. It doesn't have to be the real username, substitute Fred Bloggs for the real name to mask it if necessary.
I believe that username may either be %username% to retrieve the name from the system, or a real literal. The problem with this is that such names often contain spaces, you'd need to "Enclose the full filename in quotes".
See - had you told us _sLogFile=E:\Fred Bloggs\Documents\Status\OfficeStatus.txt it would all have been a lot clearer - presuming that my guess as to the cause of the problem is correct.
Perhaps you should look for files named like E:\Fred which is where the expected output may have ended up.
this is my first post. I am using a batch command to check if an instance of my program is already running based on its command line argument. I am able to see if it is running by using the following code:
wmic Path win32_process Where "CommandLine Like '%Account A%' AND Caption Like '%Leads Manager.exe%'"
If the process exists, I will get a full break down of the process information, but if the process isn't running i get No Instance(s) Available.
I want to be able to run an If statement, so if the result shows No Instance(s) Available. I want to run a command without displaying the process information and if it does exists, I want to echo Account A is already running
Hopefully someone with more experience can point me in the right direction
Here's a batch-file example, which may help you out:
#Echo Off
For %%A In (A B C D) Do WMIC Process Where^
"Name='Leads Manager.exe' And Not CommandLine Like '%%Account %A%%%'"^
Get Name 2>Nul|Find "Name">Nul && (
Start "" "C:\Leads Manager.exe" -- "C:\Account %%A.ini")
This example uses the outer For loop to choose the Account letters, it is therfore checking to see if Leads Manager.exe is running with a commandline containing the string Account A, Account B, Account C or Account D, and if not it should run Leads Manager specifying the path to the appropriate account. (Please note that your .exe and .ini file paths both contain spaces, so I have doublequoted them, but left the rest of the command as you wrote it in your comment. You may want to consider checking that what you provided was correct and adjust it as necessary before testing, or replace that line entirely with a simple Echo Is Not Running) || Echo Is Running) statement, or perhaps run another batch file instead).
How can I check for a particular text logged to a file in Win 10 ? There is a SAS daemon that fails occasionally and at which point logs a message to a log file (C:\SAS\logs\daemon_error.log). The message is logged (with timestamp) only when the error occurs. I want to write a program (and schedule to run every 15 mins) which would check the occurrence of any error-message since the last error recognized. For e.g. if the last error was logged on July 15th the file would have looked like :
07-15-2018 13:21:42 : Incorrect parameters
Now if some error gets logged again today, it would look like below, at which point the script should trigger and identify it and send an email to a list of intended recipients. I presume there needs to be a mechanism to store the last timestamp when the error was recognized so that it only identify errors logged after the last one.
07-15-2018 13:21:42 : Incorrect parameters
09-10-2018 04:32:09 : Temp directory full
How can I accomplish this thru a batch file or perhaps any windows event(s). I do not have much knowledge on Win systems as I primarily worked on Unix. Can anyone please help ?
Thanks
When I understood you correctly, you want to check for timestamp only to know, if there are new errors since the last check, but don't necessarily need to know, which errors. For that, I suggest using the "Archive attribute" (Windows sets this attribute at each write access to the file)
#echo off
:loop
timeout 900
dir /aa "C:\SAS\logs\daemon_error.log" >nul 2>&1 || goto :loop
echo The file was changed!
attrib -a "C:\SAS\logs\daemon_error.log"
goto :loop
The dir command will not find the file when the Archive attribute is not set (/aa) (or the file doesn't exist) and || goto :loop will then jump to the :loop label.
>nul 2>&1 will just discard any output of the dir command - we don't need it, just the errorlevel)
If the file was found (the Archive attribute is set, so we know, there was a write access), the code continues. Replace the echo command with the command to write an email (there are several questions/answers about that on SO).
attrib -a unsets the Archive attribute.
Note: Instead of the loop, I would set up a scheduled task, but keep with the loop for troubleshooting until you're sure, it works as intended.
If from inside a bat file you called another batch file but still had a few remaining operations to complete, how can you make sure that the call to first bat file will after completion or error, will return to the file that called it in the first instance?
Example:
CD:\MyFolder\MyFiles
Mybatfile.bat
Copy afile toHere
or
CD:\MyFolder\MyFiles
CALL Mybatfile.bat
COPY afile toHere
What is the difference between using CALL or START or none of them at all? Would this have any impact on whether it would return for the results of the copy command or not?
As others have said, CALL is the normal way to call another bat file within a .bat and return to the caller.
However, all batch file processing will cease (control will not return to the caller) if the CALLed batch file has a fatal syntax error, or if the CALLed script terminates with EXIT without the /B option.
You can guarantee control will return to the caller (as long as the console window remains open of course) if you execute the 2nd script via the CMD command.
cmd /c "calledFile.bat"
But this has a limitation that the environment variables set by the called batch will not be preserved upon return.
I'm not aware of a good solution to guarantee return in all cases and preserve environment changes.
If you really need to preserve variables while using CMD, then you can have the "called" script write the variable changes to a temp file, and then have the caller read the temp file and re-establish the variables.
call is necessary for .bat or .cmd files, else the control will not return to the caller.
For exe files it isn't required.
Start isn't the same as call, it creates a new cmd.exe instance, so it can run a called batch file asynchronosly
The `CALL' statement was introduced in MS-DOS 3.3
It is used to call other batch files within a batch file, without aborting the execution of the calling batch file, and using the same environment for both batch files.
So in your case the solution is to use CALL
Okay, I actually didn't even really think about the fact that if you call a batch (regardless of the 'type', i.e. '.bat', or '.cmd') that it won't return if you don't use call.
I've been using call myself though for a different reason that I am actually pretty surprised that no one else has brought up. Maybe I missed it. MAYBE I'M THE ONLY ONE IN THE WORLD WHO KNOWS!! :O
Probably not, but I'm going to drop this knowledge off here because it's super useful.
If you use call you can use binary logic operators to decide how to proceed based on the ERRORLEVEL result. In fact, I always was flabbergasted on how && and || existed in DOS and COULDN'T be used this way. Well, that's why.
The easiest way to test this is to create a return.cmd with notepad, or from the command prompt like so:
c:\> type con >return.cmd
You will now notice the cursor goes down to the next line and hangs. Enter:
#exit /B %1
And then hit ENTER, and then CTRL-Z and that file will be created. Good! You may now feel free to try the following two examples:
call return.cmd 0 && echo Huzzah! A Complete Success! (Or cover up...)
call return.cmd 123 || echo Oops! Something happened. You can check ERRORLEVEL if you want the tinest amount of additional information possible.
So what? Well, run them again with the 0 and the 123 swapped and you should see that the messages DON'T print.
Maybe this multi-line example will make more sense. I use this all the time:
call return.cmd 0 && #(
echo Batch says it completed successfully^^!
) || #(
echo Batch completed, but returned a 'falsey' value of sort.
call echo The specific value returned was: %ERRORLEVEL%
)
(Note the 'call' in the || section before the second 'echo'. I believe this is how people got around not having delayed expansion back in the day. If you DO have delayed expansion enabled (via. setlocal EnableDelayedExpansion inside a batch OR launch a command prompt with cmd /v:on then you can just do !ERRORLEVEL!.)
... This is where I have to apologize and say if you have if ERRORLEVEL trauma in your past you should stop reading. I get it. Trust me. I thought about paying someone on fiverr to remotely type this for me, but for completeness sake I'm just going to take one for the team and mention that you can also do the following to check errorlevel:
if ERRORLEVEL 123 #echo QUICK! MOTHERS, COVER YOUR CHILDREN'S EYES! FINGERS ARE BEING UNDONE! :'(
If you've never typed that before then GOOD! You will live longer without having to read up why exactly you aren't getting the results you expect. Cruel is the word you're looking for, not 'quirky'.
The important part that I really want to get across however is that if you try this and DON'T use 'call' it will ALWAYS execute the 'true' branch. Try it for yourself!
If I'm missing something, or you know a better way to do this, please let me know. I love learning stuff like this!
Additional information I mentioned:
I have known for quite some time that you can put redirects BEFORE commands like so:
>nul echo. This won't be displayed!
But I accidentally discovered the other day by being a dumdum that you can apparently also do:
echo A B>file.txt C
And was REALLY surprised to find a file.txt which consisted of "A B C". It appears yo can place them ANYWHERE, even inside the command. I've never seen anyone do this, nor mention it, but I HAVE seen people mention that you can prefix a line with them.
Maybe it's a bug exclusive to Windows 10 or something. If you have another version and wanna try it out and let me know I'd be interested in what you find out.
Stay nerdy!
I have tried prefixing lines with semicolons, 'REM', etc.. but no matter what when I run my batch file I keep getting "unknown command REM whatever"
"REM test" It is not recognized, and it is windows vista. I simply get "rem" output back to my console.
That's entirely normal behavior. Batch files are simply sequences of commands that are run one after another. So every line will get output to the console as if it were typed there.
H:\>echo rem test > test.cmd
H:\>test
yields the output
H:\>rem test
as if I typed rem test directly to the console.
You can suppress this by either prefixing the line with #:
#rem test
or by including echo off in the batch file:
#echo off
rem test
If I put ":: test" and execute it I get back "Test".
Can't reproduce here.
If I put "; test" it recursively executes itself
A semicolon at the start of the line seemingly gets ignored.
If you're talking about cmd.exe batch files under Windows, you can use:
rem this method or
:: this method.
For bash and a lot of other UNIX-type shells, you use:
# this method.
I'm pretty certain you're not using cmd.exe since that would give you an error like:
'rem' is not recognized as an internal or external command,
operable program or batch file.
rather then:
Unknown command ...
If you are using a UNIX-type shell, the # character is almost certainly what you're after. If you let us know exactly the shell you're using, we can probably help out further.
you probably created an UNICODE file. These files contain 2 bytes header named BOM
which is not shown by any editor but cmd attempts to execute them and fails.
To make sure this is indeed an issue: type any other command at the very beginning
of your file and see it throws the same error - for example #echo test
To fix it, just create a new plain text file and copy content of the original file there.
then remove the original file and replace it by the newly created one.
In my case the problems are line endings. Somehow Maven or the Jenkins pipeline running on a Linux machine changed the line endings from Windows style (CR LF) to Unix style (LF). Changing them back solves the issue for me.