This is my code. I am making an IP finder, for Fun and practice. I want to log all of the successful IPs on a separate line for each IP. As a note, successful meaning any IPs that I get a reply from.
:ModeB
CLS
Echo AutoMode On
ping %RANDOM:~-2%.%RANDOM:~-3%.%RANDOM:~-3%.%RANDOM:~-3%
goto ModeB
Basically, this will randomly generate numbers within dots and ping it. It does this repeatedly. Most of these IPs will not work, but it will get replies from some of them. I want to log the IPs I get at least one reply from, and then, and only then, will it truly be an IP finder. Any advice for this project will be appreciated.
There is enough bad willed traffic in the internet, there is no need
to be obtrusive.
%Random% generates numbers between 0 .. 32768 see here
an ip octet is 0 .. 255
your approach has the problem that while verifying the success of your ping you have to store the ipaddress, the next invocation of %random% has another random result.
You should read on redirection, for /f to parse the output of a command etc. ss64.com is a good starting point.
And please choose a different learning object-
To start with, there are much more effective ways of scanning lots of ip's to see which are active, such as the free, open source tool nmap.
Using this method to find active hosts will most likely never find any considering the shear amount of possibilities an ip could be.
I'm not entirely sure batch actually has the capabilities to do what you are looking for, so I would recommend looking into other languages. As a recommendation, VB.NET and Python are good places to start.
Related
I have to maintain a batch script of about 3500 lines littered with GOTO. Seems that the original "developer" hasn't heard of this famous paper and modular programming.
What the script does?
The script deals with the (silent) installation/uninstallation/reinstallation of several programs using different options. It could be split in several files that deal with each program in part. The problem is that if you're trying to take a part in another file that part will still GOTO another section that needs to be in the original script.
Refactoring?
Normally you wouldn't do a refactoring without having automated tests (so you can be sure you didn't break anything), but I don't know how to do it. There's no testing framework for that.
Partial Solution
I have come up with a partial "solution" that is some kind of adaptation of characterization tests (from Working Effectively with Legacy Code by Michael Feathers) and approval tests:
- create another script: test.py that replaces all commands (like copy or msiexec) with echo,
- redirect the output to a text file (good.txt),
- change the original batch script,
- run the test.py script again and save the output to another text file (current.txt),
- diff good.txt and current.txt -> if there are no differences then I didn't break anything, but if they are different I need to check if I broke something.
Problem with partial solution
How can I capture and replace all the commands? I could make a list of commands to replace, but there are also a lot of string concatenations to get the name and path of the program to be installed.
CMD level capture/hook?
Is there any way I can hook into the command line interpreter (CMD.exe) so I can replace on the fly all the calls to installers with echo?
Other suggestions?
Do I approach the problem in the wrong way? Can I do it better somehow? Do you have some advice I could use?
You could replace all COPY, DEL or CALL with %COPY%, %DEL% ,...
So you can use the same file for production and also for the tests.
#echo off
if not defined UNITTEST (
set "COPY=COPY"
set "DEL=DEL"
set "CALL=CALL"
)
%COPY% src dest
%DEL% somefile.txt
%CALL% installer.exe
And from your unittest.bat, you could start it via
#echo off
set "COPY=>>trace.log ECHO COPY"
set "DEL=>>trace.log ECHO DEL"
set "CALL=>>trace.log CALL ECHO "
del trace.log
set "unittest=Active"
call production.bat
fc good.txt trace.log
I'm not an expert in Batch, but I have done my fair share of it. With that said, I can offer a few tips.
Forget trying to do it all at once. Batch is very hard to debug. Echoing out to a log file helps a lot, but it will not capture everything you need if something goes wrong.
Work on breaking out the exe and msiexec calls into self-contained scripts. It is much easier to test the small script for the functionality you desire. Once you have that working, it is simple to call that script from the "Master" script.
Establish a good protocol for passing args to, and return codes from the smaller scripts. If there are common settings needed to be used for all the scripts consider using a central settings file.
GOTOs are not the devil, unless they pass control all over the place. Normally there are two good reasons that I know of to use GOTO’s.
Skip past a block of code that does not need to run.
To SET values into variables. Note there is a bug that can prevent variables from having their value set from within an 'IF' statement block. That little bug caused a big headache for me at one time.
Calls to a label might be better option at times.
Depending on how far back the legacy support is required, consider using Powershell when possible. The power and debugging capabilities of Powershell far out way the benefits of simple scripting of Batch. Which at 3500 lines simplicity has already been lost. You are already looking at Python, so maybe that could be used instead.
If you need a break point, use Pause. ECHO all the settings you need to examine right before the pause. This is as close to a break point I have found for batch.
Echo the command you intend to run to a log file and actually run it.
Write small verification scripts to be used independently or with the “Master” script to confirm you are getting the results you are expecting.
Use the right tool for the job. I like to use EditPadPro, RegexBuddy, and BeyondCompare for batch editing and comparing differences. There free tools that can be used too NotePad++ and Windiff. Making many edits in a file of that size is best handled by a good editor. IE inserting an echo at the beginning of a line that calls a cmd.exe.
Remember it is scripting not programming. While there is a lot of overlap of the two, the same exact approach to a problem may not be viable between the two.
Always make a backup copy of the scripts as a whole before mucking around. A fallback position is greatly appreciated when there is one small bug that you can’t find.
If it ain't broke... well you wouldn't be working on it if everything was working just fine.
Always test changes. And when you are done test it again. After that have someone else test it.
Just my .02. I’m sure someone else can chime in with more advanced advice. My knowledge on Batch has been acquired from the school of hard knocks, supplemented by ss64.com
I have a batch file that encounters several errors. These errors require the command prompt to be forcefully closed. Which causes me to have to open the file again to fix the issue.
Due to the nature of this application it is required to run all the time.
I'm looking for a way to automate the file to restart when it encounters an error. Is there a command I can do this with?
Could you please describe in detail and why the command accomplishes such a resolution?
Update:
What I would recommend to accomplish your goal, would be to turn your batch into a Service. (Documentation here) By converting your batch into a Service it no longer becomes subject to users being logged in, permission issues, it will run as a SYSTEM ACCOUNT. This in itself can alleviate a lot of anger for the process.
After you've completed that, you can write a batch file that ensures that your Service is indeed running. Your current issue, is it doesn't automatically restart. Well, a Service always runs- Even if it has an error it will still attempt to run.
Which means unless it has a Fatal Exception your Service should always work- But for certainty you can create a batch that will ensure your Service is running.
An example:
:START
timeout 3600
for /F "tokens=3 delims: " %%H in ('sc query "MyServiceName" ^| findstr "
if /I "%%H" NEQ "RUNNING" (
NET START "MyServiceName"
REM Service has Started...
)
)
GOTO START
So in theory every 3,600 seconds it will test if your Service is running, if it isn't it will start the Service for you.
Important:
This is more the proper way to resolve your issue, rather then circumvent it. However, as I noted your batch should still implore Exception Handling to ensure your application doesn't fall into an unusable state. This still isn't the best way, as it should implore Exception Handling and Verification to test against it's state.
As I mentioned before, you have a lot of methods to solve your issue. However, your thinking in a Linear Mindset. Which means:
Execute Command, Goal Guaranteed.
If I do this, this happens.
Essentially based on the minimal example I saw, it looks like you've created an infinite loop to continually execute your command. My question to you: When your loop has an error, how can it continue to run?
You've already stated that it happens in random areas- Nothing is random, those are more then likely areas that require some verification / testing to ensure it remains in a proper state. The faster your identify the potential problems, the more effective your program can run with no errors.
Hopefully that helps-
What exactly does your batch application do?
The reason I ask is because you can circumvent the issue with Windows Task Scheduler which allows you to configure some parameters to auto start and auto open particular applications based on your specified criteria. Will it be ideal? Will it truly automate to your needs- More then likely not.
As mentioned above by GolezTrol, the cause of your error will be the more important aspect to resolve your issue. Based on your remark
The errors are different each time, to be honest.
That could be an indicator that the batch script doesn't adhere to testing but rather assuming it successfully completed. Without any underlining information such as:
Function
Code Example
Where an error occurred, and during what task.
It makes it relatively difficult to point you in the proper direction. One thing that I would consider is IF. This is a fundamentally basic task but is quite important-
if(Directory.Exists(dirName))
{
// Do This
}
else
{
// Do This
}
I find the C# outline an easier method to understand the purpose of the IF. You can actually implement something similar in your batch. You would accomplish it like this:
if exist { insert file name } (
rem file exists
) else (
rem file doesn't exists
)
or you can accomplish it like this:
if exists c:\myFile.bat notepad c:\myFile.bat
If C:\myFile.bat exists, then open notepad. The reason this is an important is because if the variable doesn't exists, then it can not be affected. This allows your application to essentially make decisions in a very primitive manner.
You have quite a bit of flexibility- There are a lot of examples on this topic because batch programming has been around for a very, very long time. Another alternative would be to eventually move to Powershell. It will have access to the Windows Management Interface (WMI).
Hopefully this points you in the right direction, without more information our answers may not be much help.
I believe, that easiest way is to create one more .bat file with GOTO statement:
#echo off
:startover
echo (%time%) App started.
call "c:\app.bat"
echo (%time%) WARNING: App closed or crashed, restarting.
goto startover
Possibly this will fix your problem:
http://nssm.cc/usage
Basically what it does is you adding some bat file to nssm and making it a service.
In "Action on exit" part it says:
To configure the action which nssm should take when the application exits, edit the default value of the key HKLM\System\CurrentControlSet\Services\servicename\Parameters\AppExit. If the key does not exist in the registry when nssm runs it will create it and set the value to Restart.
Hullo, I was just wondering whether a plain SET parameter could be used for obfuscations or any other protection from antivirus in Windows batch files.
I ask because I recently obtained the two "famous" batch virus scripts "PiFv," and "meLT." For study of course. They kept getting detected by antivirus, so I would disable it, study for a while and it would be deleted again. Lucky I have internet ;) Anyway, I tried to think of a way to hide the virus'.
I thought maybe because they are analyzed by string, merely a text change would help. So I used inconspicuous words like so
SET hello="# Echo off"
%hello%
And so on. Unfortunately, Norton was clever enough to suss it (surprisingly) though it's status was lowered from "Infectious" to "Heuristic." I figured if it had gone from yes to maybe this could work.
Next I went on single letter changes making words, example, if I was to print "infect;"
set z=i
set h=n
set j=f
set x=e
set d=c
set q=t &echo %z%%h%%j%%x%%d%%q%
That has half worked. Although a lengthy process I think if a set alphabet was established then changed it might. Anyway, the half working. It is classed heuristic when off a USB, but not classed if off a floppy. Why? Also, do you think this is a good idea?
Half way through reading your question I thought the same as your second idea, splitting the words.
I can't test as different AV's will detect different things, but maybe try splitting them into half's instead of single letters, so it doesn't take as long to do.
set z=inf
set h=ect
echo %z%%h%
Another option would be to read in the complete commands from a text file
set /p z= <command.txt
echo %z%
I've been racking my brain trying to get my softphone to dial numbers on web pages. I've gotten the browser to pass the number through to the softphone, but it adds tell:+ to the number and won't call out.
As a matter of last resort, I want to create a batch file to remove the tel:+ from the number. I have never written one before, but I imagine that it would be relatively simple.
The batch file just needs to open the tel: urls and remove tell:+ from the number before passing it on to the softphone.
I would really appreciate it if someone could point me in the right direction.
#echo off
set "URI=%~1"
set "URI=%URI:tel:+=%"
somecommand %URI%
Pass the URI as argument.
See help set for a detailed description.
found this batch file with timer. I'm not very familiar with *.bat files but have foundout the following
THAT 01 is the time in seconds
PING -n 01 127.0.0.1>nul
however im not sure what the rest means rather then just go and use it could someone please explain what all other items in this snippet do/ represent
thanks
It's a sneaky sleep statement. I've used it before to get a delay in a cmd.exe script without having to resort to external utilities.
However,
ping -n 21 127.0.0.1 >nul:
will generally give you about a 20 second delay because the first ping goes out immediately (only the subsequent pings are sent after a 1-second delay).
If you try your variant (with 01) without the >nul bit, you'll see it returns immediately. If you try it with 21, it should take about 20 seconds, and you'll see why, hopefully :-).
As to what all the bits mean:
ping is the ping executable, meant to check whether you can communicate with a specific IP address (it's less useful than you think since many sites will block ICMP (ping) packets while still allowing real traffic.
-n 21 means to try 21 times (with one second between each, although you can change that with another parameter).
127.0.0.1 is the loopback address, basically "this computer". You ping your own computer so that no network delays are introduced (and to not annoy your target if everyone on the planet decided to use slashdot.org for example).
>nul just means to send all the output to the bit-bucket so you don't see it on the console.