So, I am continuing to revise the program I described in my previous question Incrementing FOR loop for each line in a text file (batch).
As I am moving along, I am attempting to create a portion which will only grant access to a text document while the program is running. To do this, I am granting access on start up with net use. However, my dilemma is that I do not know of any event handler in batch that could make my program run net use /delete (<= I know the syntax is incorrect; besides the point) whenever the user closes the window (as in, literally click the red "X").
What event, or any command in batch, would allow me to do this?
Edit: I found something about the /wait command but I have no idea how this would help me with running the net use /delete command.
Instead of net use, you could use pushd with a UNC path to create a temporary network drive mapping. For example:
pushd \\localhost\c$\Users\%username%\Documents
Then, regardless of whether you popd, endlocal, exit /b, or the user terminates the script with the red X, the temporary mapping will be deleted at the end in any case.
Just make sure you setlocal at the top of your script, or at least somewhere before you pushd. It's generally good practice to put setlocal at the top of every script immediately after #echo off anyway, unless you have a specific reason not to.
If you need to authenticate, then use a combination of net use and pushd. Use net use without a drive letter, then pushd \\UNC\path && net use \\computername /delete. Here's a more complete example:
#echo off
setlocal
set "remotePC=minastirith"
set "user=%remotePC%\adminUser"
set "pass=Password"
:: establish an authenticated session
net use \\%remotePC% /user:%user% %pass%
:: pushd and immediately terminate the net use
pushd \\%remotePC%\share && net use \\%remotePC% /delete
:: The next two commands demonstrate that even though
:: the session has been disconnected, pushd still has
:: temporary access.
cd
dir
pause
:: When you popd, endlocal, exit /b, or close the window,
:: there's no longer an authenticated session. Another
:: attempt to pushd should result in an error.
popd
pushd \\%remotePC%\share
pause
Add a second batch. Won't help for the user clicking close button (you need to write a real program for that).
Batch1
Net use etc
Call Batch2
Net Use/delete etc
Batch2
Your commands
When batch two is terminated the rest ofthe commands in Batch1 runs. You need to read help call /?.
Related
With my .bat I would like to:
open the xlsx file,
waiting 2 min,
close the file with save options
copy this file to another folder.
For now I can copy and paste the file, but I don't know how to open it, with a cmd function, and save it.
Thank you for your help.
My code is :
#echo off
cmd "O:\XXXX\*.*"
xcopy/y "O:\XXXX\*.*" "O:\XXX\"
pause
Marie (TooLong;ToRead) in disjointed comments
I suggested, A simpler alternative method to do what you need on this
occasion is to use a simple command line tool see Orlandos Sendkeys
Utility (the example is almost what you want to do)
download sendkeys from cpap.com.br/orlando
see how the demo runs
open excel with a blank sheet and at a CMD> run this demo string
SendKeys.exe 1.5 10 "Microsoft Excel" "Hello!~{PAUSE 2}After 2s.~{PAUSE 2}%(FS)~"
adapt to your own version of excel keys since the %(FS) is ALT File Save in English
you replied
#KJ Thank you, KJ, unfortunately I can't download Orlando with my PC.
So we continue to doing it in a more dirty fashion, but you still need a means to save the file by invoking an autosave which would most easily be done using an extended excel macro in your source .xlsm, anyway
after all these changes your non working file should now be replaced in your question as
#echo off
start "Excel Running" /MIN EXCEL.EXE "\\XXX\Fichier.xlsm"
REM add a delay of **2 minutes !** whilst sheet recalculates before saving a copy
timeout 120
REM copying a file that has NOT been saved using keys at this point will NOT
REM be what you really need to solve your problem unless you use a macro ?
REM see Later
xcopy/y "\\XXX\Dossier_avant*.*" "\\XXX\Dossier_apres\"
REM add a 3 second delay to check above worked but is not really needed
timeout 3
REM temporary for debugging. Later just REM it out
TASKLIST /M |Find /i "exce"
REM this line should be working with either a SUCCESS: or ERROR:
TASKKILL /T /F /IM excel.exe
REM keep this line for seeing errors above, once happy, it can become REM PAUSE
PAUSE
I think that IF you are constrained (by IT policy) to the command line it is best you write your own autosaving macro, however, MY problem is I dont know if you need it for more than one input.xlsm.
So save this as OpenRunSaveExit.vbs in your working folder where your .bat is. There is a reason I did NOT use spaces or & in the name for a later step.
Set WshShell = WScript.CreateObject("WScript.Shell")
' You may need to include the path to excel.exe if it is a portable version like mine
WshShell.Run "EXCEL.EXE "+"\\XXX\Fichier.xlsm", 9
' 120000 milli-seconds = 2 minutes
WScript.Sleep 120000
' These are the English key combinations for ALT+File+Save . SO alter or remove if not needed
WshShell.SendKeys "%FS"
' These are the English key combinations for ALT+File+eXit . SO alter if needed for french excel
WshShell.SendKeys "%FX"
' Lets us wait 2 seconds for clean closure
WScript.Sleep 2000
As Peter has pointed out in his answer you need to /WAIT before xcopy and depending on how your vbs file handling is set-up you may not need Wscript in the start line
NOW replace your .bat with this
#echo off
start /WAIT Wscript OpenRunSaveExit.vbs
xcopy/y "\\XXX\Dossier_avant*.*" "\\XXX\Dossier_apres\"
pause
And check it runs without the need for taskkill.
Finally why use a 2-4 line .bat since a desktop shortcut would potentially be easier to use. So make a shortcut for the .vbs file (right click the .vbs, and in English its Create Shortcut) and wherever it is built move it to your desktop.
Then change the properties like this (where & has a special meaning so the .vbs filename must NOT have spaces or &.)
%comspec% /c "start /wait wscript.exe OpenRunSaveExit.vbs & xcopy/y "\\XXX\Dossier_avant*.*" "\\XXX\Dossier_apres\" & pause"
P.S. I forgot to add Peters start / wait in this image until later
You can't interact with Microsoft Excel (or most of other programs) through Batch unless they provide such an interface. There is however an option to do it with VBS i.e. via an interface Microsoft Excel supports for interacting with that software.
For just opening the program check start command e.g.:
start /B excel.exe <filename>
then you can wait for the user to both edit and save the file for two minutes or also utilize pause if you don't want to introduce a race condition between saving and copying with xcopy.
Alternatively use start like this:
start /WAIT /B excel.exe <filename>
so the opened file blocks the operation and once it closes (no edit or saving by the user guaranteed) then it'll unblock and xcopy would take place without any time-dependent feature.
How can I write a batch file that runs cmd.exe, enters the partial command robocopy then waits for user input to complete and execute the robocopy command? It seems like it should be the simplest thing to do but no method I've tried enters the command in such a way as to hold and wait for user input and then successfully execute the completed robocopy command
For example:
#echo off
set var="robocopy "
cmd.exe %var%
appears to work but then, for example, user-inputting /? to bring up robocopy's info instead brings up cmd.exe's info
Another example:
#echo off
cmd /k robocopy
Runs robocopy with no destination/source folders or switches, then closes robocopy and waits for a new user-inputted command.
what I'm trying to do is have a batch file that when I click it a cmd window will open with the partial command robocopy already entered ready for me to complete the command with source/destination/switches and execute it with an enter key press - I use robocopy all day long so this would be a big time saver.
it's not possible in the way you seem to think. That would mean to mess with the keyboard buffer (was pretty common with the C64 back in those times, but it's not possible in (pure) batch).
But the following should give you a good start for automation. It assumes, you use the same parameters each time and just want to give it a source and a destination folder. Adjust to your needs (especially the params - I added /L to prevent it from unwanted actions while testing):
#echo off
set "command=robocopy"
set "params=/L /E /MOV /MT:12 /FP /log+:robocopy.log /TEE"
set /p "source=Enter Source: "
set /p "destin=Enter Destination: "
%command% "%source%" "%destin%" %params%
The cmd.exe or cmd.exe /k isn't necessary, until you want robocopy to work in a new window.
Thanks. Thought I'd try writing a batch file to kill another open cmd session that is constantly open churning out lots of scrolling info.
I got a bit carried away and am now outta my league so to speak.
Basically I am trying to search for "£000.00" within a each emerging line of tet that appears in the other running open command window. The running command session is named in the window as C:\windows\system32\cmd.exe but is does have a valid .exe process name in task manager while running and open.
The batch file code below is as far as I've got.
The idea is that when the above string is found in the other process that process/program get closed down them re-launched.
This is as far as I've got.
#echo off
#echo off
title Shut down other process and relaunch
:loop
start /d "C:\Users\Desktop" ActiveDOSprogram.exe
:: #setlocal enabledelayedexpansion
:: #echo off
:: set stringfound=1
find /c "*£000.00*" C:\Windows\system32\cmd.exe && (echo found %date% %time%:~0,-3% >> "%USERPROFILE%\Desktop\Crash_Report.txt"
taskkill /IM ActiveDOSprogram.exe /F
timeout /t 20
start /d "C:\Users\Desktop" ActiveDOSprogram.exe
goto loop
So when I tried this without any variables and in a loop and I think i nearly blew my PC!
Reason I'm stuck is I'm really a novice at this (but trying) and I got as far as I think I need a variable in there somewhere, that only move's to the next line (taskkill+restart) when £000.00 is found in the other process.
Thanks
wingman
Hi everyone first time posting, looking for a review of a batch file that I can't get to work correctly:
#echo Mounting ServerName as local drive
net use M: \\ServerName\"R Share"
#echo Clearing IE Cache
taskkill /im iexplore.exe /f
M:\"R Share"\PSExec\psexec.exe -l c:\windows\system32\RunDll32.exe InetCpl.cpl,ClearMyTracksByProcess 32
#echo Removing ServerName
#net use M: /delete
#echo IE Cleared
#pause
The point of the script is to mount a share as a drive, close any open IE windows, then run psexec to clear IE saved credentials, then unmount the drive. I keep running into a system error 53 when trying to mount the drive initially and want to make sure i'm not missing anything in my code. I've attempted to mount the drive using name and IP of the machine and either way I still run into the SysError 53 even though the share is reachable in Explorer. Thanks for any help you can provide.
P.S. I also tried executing PSExec directly from the network location
It is wrong to enclose just a part of an argument string in double quotes on containing a space character or one of the characters &()[]{}^=;!'+,`~|<>. The last 3 characters can't be used in a file/folder name, just in other argument strings.
Windows command interpreter respectively the startup code of the executable (= code of executable run before main parsing command line string) must do a lot of extra work to automatically correct a wrong quoted argument string if the startup code of executable does such an auto-correction at all.
See answer on batch file: list rar file in specific folder and write result into text file and answer on How to set environment variables with spaces? for details on what could happen on wrong double quoting an argument string.
So wrong is:
net use M: \\ServerName\"R Share"
Correct is:
net use M: "\\ServerName\R Share"
Argument 0 is net, argument 1 is use, argument 2 is M: and argument 3 is "\\ServerName\R Share".
However, net.exe has a startup code which interprets \\ServerName\"R Share" with automatic correction as \\ServerName\R Share. So this is not the coding error resulting in system error 53 message.
System error 53 is caused by assigning \\ServerName\R Share to drive letter M: and using next:
M:\"R Share"\PSExec\psexec.exe
The share R Share is already included in M:. So the correct line would be:
"M:\PSExec\psexec.exe"
The entire batch code with corrections applied:
#echo off
echo Mounting ServerName as local drive
%SystemRoot%\System32\net.exe use M: "\\ServerName\R Share"
echo Clearing IE Cache
%SystemRoot%\System32\taskkill.exe /im iexplore.exe /f
"M:\PSExec\psexec.exe" -l c:\windows\system32\RunDll32.exe InetCpl.cpl,ClearMyTracksByProcess 32
echo Removing ServerName
%SystemRoot%\System32\net.exe use M: /delete
echo IE Cleared
pause
It is better to specify executables in system directory of Windows with full path and with file extension because then Windows command interpreter must not search for those executables using local environment variables PATH and PATHEXT. A batch file being as much independent as possible on current values of those two environment variables is a batch file working also on wrongly updated system PATH, see for example Why does the command "Timeout" in a batch file suddenly not work anymore?
This batch code could be optimized by using command PUSHD which pushes the current directory path on stack and sets the specified directory as current directory whereby with enabled command extensions a UNC path is automatically mapped to next free drive letter. Command extensions are enabled by default, but it is of course possible to explicitly enable them for security. The command POPD removes the mapping done by PUSHD and sets the current directory back to the directory pushed before on stack.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
pushd "\\ServerName\R Share"
%SystemRoot%\System32\taskkill.exe /im iexplore.exe /f
echo Current directory is: %CD%
PSExec\psexec.exe -l c:\windows\system32\RunDll32.exe InetCpl.cpl,ClearMyTracksByProcess 32
popd
echo IE Cleared
endlocal
pause
Note: PUSHD and POPD can't be used if user name and/or password must be also used on command line to successfully map the network share to a drive letter and accessing the directories and files on that share because the batch file is running with a user account not having required access on network share.
Hints regarding terminating versus killing IE
I think using TASKKILL without /f would be better here. Internet Explorer should not be killed by operating system as done on using option /F. It would be better to use TASKKILL without /f which results in sending to IE the event message to close/exit/terminate itself which IE processes usually and terminates itself gracefully. Of course a delay of about 1 to 2 seconds should be added before the next command is executed to give IE the necessary time to gracefully terminate itself.
The optimal solution would be using TASKKILL without /f to send to IE the WM_CLOSE message, wait 1 or 2 seconds, check with TASKLIST if IE really terminated and otherwise use TASKKILL with /f to kill not responding IE process by the operating system.
And last it is possible that multiple instances of Internet Explorer are running and therefore it would be better to use TASKLIST to get the process identifier (PID) of each running Internet Explorer instance if there is an IE instance running at all, use TASKKILL without /F on each running instance of IE using PID, check after 1 to 2 seconds with TASKLIST if all instances of IE gracefully terminated and in case of 1 or more instances of IE are still running use TASKKILL with /F to kill those remaining IE instances not responding in the 1 to 2 seconds with terminating itself.
I wrote a script which is doing net use at the beginning and net use /DELETE at the end.
But if user decides to press Ctrl + C and exits the script, I need to do a net use /DELETE.
Is that possible? I can't find anything on google.
Sure, simply execute most of your script in a new CMD session:
#echo off
if "%~1" neq "_start_" (
net use ...
cmd /c "%~f0" _start_ %*
net use /delete ...
exit /b
)
shift /1
REM rest of script goes here
As long as your console window remains open, the net use /delete command will always fire after the inner cmd session closes. It could close because of normal run, user presses Ctrl-C, or fatal error - the final net use \delete will still fire.
My idea is similar to dbenham's. Took me forever to figure out how to minimize the current console window though. I banged my head against the wall trying to get the cmd window not to ignore an Alt+Space keypress using Wscript.Shell's .SendKeys method. Finally I turned to PowerShell to handle minimizing and restoring the working window.
The advantage to this over dbenham's is that you'll inevitably have some rectal-cranially inverted user who gets bored with the running of your script and terminates it with the red X. dbenham's won't catch that, but mine should.
#echo off
setlocal
if "%~1" neq "wrapped" (
rem :: Map network drive
net use y: \\computername\c$ >NUL
rem :: minimize this console
powershell -windowstyle minimized -command ""
rem :: relaunch self with "wrapped" argument and wait for completion
start /wait "" cmd /c %~f0 wrapped
rem :: After script completes or user interrupts, remove drive mapping and restore window
net use y: /delete >NUL
powershell -windowstyle normal -command ""
goto :EOF
)
:: Main script goes here.
:loop
cls
echo Simulating script execution...
ping -n 2 0.0.0.0 >NUL
goto loop
There is a very simple solution. Just write:
ping -l www."site".com -t 65500>nul
before your net use /delete command. The only way to break that command is to press ctrl+c.
By example:
net use "arguments"
ping -l www.google.com -t 65500>nul
net use /delete
This is a good way to detect ctrl+c, but beware of the site address you write, because it risks to make that site crash. You should, by consequence, write the address of an unusual site, or of a site of your own(Attention: the site must be existing), like a blog or something like that.
I don't think this is possible. At the beginning of your script, you can use:
net use /delete 2>nul
net use g: \\server\sharename /persistent:no
Or you could try pushd instead of net use...
If Command Extensions are enabled the PUSHD command accepts
network paths in addition to the normal drive letter and path.
If a network path is specified, PUSHD will create a temporary
drive letter that points to that specified network resource and
then change the current drive and directory, using the newly
defined drive letter. Temporary drive letters are allocated from
Z: on down, using the first unused drive letter found.
This way, you will always have mapped drive correctly set.