I'm receiving an error message:
System.Data.SqlClient.SqlException:
Timeout expired.
I've traced this back to a command timeout which by default is set to 30 seconds. Sure enough, when profiled, completes (failed) at 30 seconds on the dot.
The easy answer would be to increase the CommandTimeout value in the code. Here's the catch - I only have an executable file to work with.
The query being run is a stored procedure that runs between 18-26 seconds normally and recently has been bumping up into the 30+ second range. I've done everything I can to optimize the query which is a single ugly select on three tables with joins. This isn't really an option anyways as the dataset will continue to grow and will be a problem again in the future.
All advice I could find here and elsewhere on the net says the only place CommandTimeout can be set is in the code after the connection is set up and there is no other way to adjust the command timeout.
I'm about ready to start decompiling the executable to try to override/set the default value of the command timeout..
Any suggestions on how I can non-programmatically increase the command timeout value, get the command Timeout value set easily or some other (hopefully) more sensible solution?
Thanks for your help!
ps - I've been reading SO for quite a while now. My reputation stinks because I always find the answer without having to post. You guys are awesome and I'm glad I finally found a way to get started!
The only way that you can change the command timeout is to update the code, if you don't have the source to the application I'm sorry to say that you are pretty much out of luck.
That is a value that is setup command-by-command, so anything external to the command will not impact it.
Related
My problem is that I need to send a shutdown command to my NAS when the UPS tells my home server that there's a power cut. I want to do this by using the (Windows 10 Home) PC server's closedown notification, which can trigger a batch file as part of the closedown event, rather than by using extra hardware. I have determined that opening a particular URL will cause the NAS to close down gracefully.
https://192.168.1.10/get_handler?PAGE=System&OUTER_TAB=tab_shutdown&INNER_TAB=NONE&shutdown_option1=1&command=poweroff&OPERATION=set
The problems seem to be related to trying to bypass dialogues that result in the browser. First it asks for credentials. I can bypass this one by including them in the URL call, like this:
start "" "C:\Program Files\Mozilla Firefox\firefox.exe"
"https://username:password#192.168.1.10/get_handler?PAGE=System&OUTER_TAB=tab_shutdown&INNER_TAB=NONE&shutdown_option1=1&command=poweroff&OPERATION=set"
Now it pops up a dialogue asking me to confirm that I want to log on as "username", again defeating my attempt to make this run unattended (I might be anywhere when a power cut strikes). Is there a way around this? Just FYI, I gave up trying to work with Microsoft Edge as it kept cutting the URL paramaeters into pieces by inserting spaces everywhere. It also kept manually complaining about the security certificate each and every time I tried it. I think I'll have the same confirmation request problems with that browser too. So I need a way to surpress all these dialogues and just make the URL call. Any thoughts please?
The lack of any answers after this question had been posted over 24 hours told me that this was a tricky one & kept me trying. After I tried everything I could think of to solve it with Window's own tool set and finding nothing worked I realised I'd need something additional to solve the problem. Finally I gave up and installed the free Autohotkey and wrote a script to do the entire job, including handling the dialogue boxes. Once it was all working I made an executable from the script for convenience so I can easily call it from the close down batch (.bat) file. This solution works. Here is the script for anyone who needs to solve a similar problem:
> runWait, C:\Program Files\Mozilla Firefox\firefox.exe
> https://admin:password#192.168.1.10/get_handler?PAGE=System&OUTER_TAB=tab_shutdown&INNER_TAB=NONE&shutdown_option1=1&command=poweroff&OPERATION=set
>
> #Persistent SetTimer, MsgBoxCheck, 3000 return
>
> MsgBoxCheck: If WinExist("ahk_class MozillaDialogClass") {
> SetControlDelay -1 ControlClick, , Confirm, SetTimer,
> MsgBoxCheck, off exitApp } else { SetTimer, MsgBoxCheck, off
> MsgBox, 4, , Debug - No Confirm Window Found. exitApp } return
Please note, to make this work with non-Mozilla programs you will need to change the ahk_class parameter. I suggest you use Windows Spy to determine the class of window you want to close. You will also need to change 'Confirm' to whatever your window's title might be.
Solved
thank you so much for helping me Jean-François Fabre, haveing someone who was thinking along with me kept me motivated to keep figuring things out myself!
what i ended up doing is using a timer script, that first boots up the scanning script, after 900 seconds of pauze the timer proceeds to open a vbs script that closes cmd and opens the timer again to do another 15 minute loop.
how to close a batch file with another batch file
C:\pokemongo-api-demo-maps>taskkill timedlocator
ERROR: Invalid argument/option - 'timedlocator'.
Type "TASKKILL /?" for usage.
currently using a runner script that boots up the batch file every 15 Sec (testing)
it wont close the batch script however
ive tried
taskkill/im cmd.exe
and
taskkill/im timedlocator.bat
the timedlocator gives the error, and the cmd closes the runner script aswell
that needs to reboot it, i cant seem to shutdown a specific cmd window without closing the other one, one solution ive tried is to make this timer shutdown script VBS and use this to shutdown CMD all together before rebooting it, but i dont know anything about what commands to use in VBS
original post
so basically i have a script that scans a area in pokemon go, unfortunately its about as unstable as it gets, so to fix this i need to reboot it about every 15 minutes, ive already tried a few things but got stuck in the end because im not very familiar with coding,
the original boot script script:
#echo off
set /p UserInputPath= Set Location-
C:\Python27\python main.py -u name -p pass -l "%UserInputPath%"
this calls the actual program that does all the work, after some research i found this How do I create a batch file timer to execute / call another batch throughout the day
and added this into the start of the script
start timer.bat
this opens a 2nd script to close and reboot after a timer
TIMEOUT /T 15 /NOBREAK
taskkill timedlocator
start timedlocator.bat
this leaves me with 2 problems i have not been able to figure out
how do i close the first batch without closing the timer CMD? ive tried messing around with taskkill and closing cmd alltogether, but this makes it impossible to boot it again
how do i automatically input a fixed streetname into the first file?
i have tried to replace the userinputpath with the streetname but that didnt seem to work.
setlocation-
at which point you enter a streetname, it sends this to the locator and it starts working,
what im trying to achieve is bypassing this first step and always send the same name.
any help with this would be much appreciated, ive been messing around w this for about 2 hours now and i have made some progress but ive seemed hit a dead end here with my limited computerskills
not sure of you're asking, but I'll try to answer anyway:
how do i close the first batch without closing the timer CMD? ive tried messing around with taskkill and closing cmd alltogether, but this makes it impossible to boot it again
You're taking it the wrong way round: create a script called runner.bat for instance and put this (untested)
:loop
start timerlocator.bat
timeout /T 900 /NOBREAK
taskkill /F /IM "python.exe"
goto loop
Your main script is started in background, and is killed and relaunched every 15 minutes (your 15 value is wrong timeout needs seconds).
how do i automatically input a fixed streetname into the first file? i have tried to replace the userinputpath with the streetname but that didnt seem to work.
=> remove the /P option and set the real value.
set /p UserInputPath=type_your_value_here
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 very basic batch file knowledge. My first script was something I found to export Oracle Discoverer reports via windows task scheduler. That's basically all I know, I've got several of them (maybe 40 or so) that run at various times, some every 30 mins. They sometimes overlap in time.
My issue is not the specific discoverer export, but the logging of errors. I want to log everything to a single log file... with excel and access processes, I can loop until free and all is good; with the discoverer batch files, the log file gets locked at the beginning and doesn't let anything else log in until done. Some of these discoverer reports may take 30 mins or more, messing up all my runs.
Here's an example of my bat file:
#echo off
echo my process %date% %time% >>c:\test.log
c:\orant\DISCVR4\DIS4USR.EXE /connect MyUserID/MyPassword#myserver /open "c:\DiscoReport.DIS" /export xls "c:\MyFile.xls" /batch 1>>c:\test.log 2>>&1
I have a bat file with several of those individual process bat files, so that they run one at a time. That works fine. But when the run takes longer than estimated, then the next run fails... because they all start by running disco, and the log file is locked throughout and until the end... Is there something I can do to just open and close it right at the time of adding the results only?
I've looked for answers, and I believe there's something that might be done with the TEE or redirecting the results maybe to null and then using that as input piped to write to the log? but I don't really know how to do this... looked, tried, weeks and weeks, can't get anything working... Pretty please, I'm sure those who know, can do this with one single line.. Pls help...
Essentially, NO - if you want the log file to contain all events in time-order.
You could have the discoverer processes create their individual logfiles and then
type discoverer.log.file >>logfile
del discoverer.log.file
which would group all of the discoverer process output together in the logfile.
Otherwise, you'd have to put up with more than one log.
I severely doubt TEE could do it as TEE would then itself need to hold the log open, so you're back at the start - But I'll emphasise I haven't tried it.
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.