How to close a file using Shell? - windows

I have a file opened named "C/Users/Desktop/textfile.txt". How do I close this using a shell script? I have tried taskkill, shutdown, "exec 1>&-" and others. Since I am new to shell, I am unable to figure out how to make it work.

textfile.txt is a non-executable file. That means you can't 'run' it, or 'kill' it. However, you can delete it - that is if some other process is not holding a lock on it.
If you want to release the lock, you have to first find the process that is holding a handle to this file, kill that process, and then the OS will let you delete the file.
From shell (command line), you can use this tool handle (https://learn.microsoft.com/en-us/sysinternals/downloads/handle) to identify which process is holding your handle. Once you get the pid (process id) from that tool, you can use taskkill to terminate that process and release the lock on that file.
c:\Program Files\SysinternalsSuite>handle.exe | findstr /i "c:/users/desktop/textfile.txt"
All said, you want to be careful when you terminate processes abruptly like this. The process won't get a chance to clean up behind itself.

Related

Find PID of conhost.exe process for the current CMD window

I want to create a doskey command that closes the current CMD console window, without affecting any other open CMD console windows.
It has to work even when cmd.exe has been run (manually or by batch file) within that window. Ordinarily I would just use the exit command, but this does not close the window if other instances of cmd.exe have been run within that window.
I therefore decided to create a 'close' command that would always close the current window regardless of what had been run inside it. I chose the PID method of window detection (to avoid issues of windows with identical titles) and then used taskkill with /F and /T switches to kill the process. It worked fine, but it had the same problem as using the standard 'exit' command.
I ran tasklist and realised that the PID of the current CMD window changes whenever cmd.exe is run within it (you can see the multiple instances of cmd.exe listed, even though no new window has been opened) so using cmd.exe PID is not a usable method. However, each window does have its own conhost.exe process associated with it (regardless of the number of cmd instances) so killing the comhost process seems to be the best way to achieve what I want.
I tried it manually and it works exactly as I wanted.
Open one cmd console window, then run cmd.exe a couple of times within that window.
Open a second cmd console window, run cmd.exe a few times in that second window.
Use tasklist to find the PID of the conhost process for the window you
want to close.
Manually run:    taskkill /PID <PID of conhost process> /F   to kill the
selected conhost.
The above immediately closes the specified console window (and all of its related cmd.exe instances) while leaving the other console window alone.
I therefore just need to replicate the above process in a batch file so that I can use my doskey command to call that instead of my existing cmd PID checking code.
This is this code that I am using for current cmd PID detection (which I found online). I don't understand it (I'm a code newbie) but it works perfectly.
I then looked for method to determine the conhost PID based on the exiting cmd.exe PID of the current window, but I couldn't find anything except for this, which did not work (and which also caused various other problems with unrelated existing commands in my batch file).
Maybe there is an much simpler way of achieving my goal, but if killing conhost is the way to go then it seems to me that a modified version of the code below (to make it find the current conhost PID instead of the current cmd PID) would be the answer, because works reliably in a batch file very few lines of code.
set T=%TEMP%\sthUnique.tmp
wmic process where (Name="WMIC.exe" AND CommandLine LIKE "%%%TIME%%%") get ParentProcessId /value | find "ParentProcessId" >%T%
set /P A=<%T%
set PID=%A:~16%

Command line options for retrieving all of the files being accessed by a particular program

I'm trying to access the files being used by a given program in Windows, via a command line prompt in a .bat script. I've found the program Process Monitor, but can't find a CLI way to do this. How might I do this?
What you're looking for is Handle (also from Sysinternals), not Process Monitor.
Handle application must run elevated (administrator)
handle -p myproc
Will return all handles for processes begin with the 'myproc'.
handle -pid 1234
Will return all handles for process with pid 1234.
You could also use Process Explorer if you want GUI.

How do I tell a windows batch script to execute the next line without waiting for the previous line to finish executing?

I'm setting up a .cmd script to be run on startup for a pseudo-server (It's actually a laptop, but that's irrelevant) to automatically launch pageant, load an SSH key, connect to an SSH server using Putty (Pageant would automatically authenticate with the key), then launch mIRC which in turn has a series of scripts setup to operate as an IRC bot and automatically connect to networks using putty as an SSH tunnel.
With that in mind, I have the below code in a startup.cmd file:
"C:\Program Files (x86)\PuTTY\pageant.exe" c:\Path\To\Private\Key.ppk
"C:\Program Files (x86)\PuTTY\putty.exe" -ssh user#host
"C:\Program Files (x86)\mIRC\mirc.exe"
EXIT
When I test run this file, the command prompt runs the first line, launches pageant, and then sits there and does nothing until I close pageant completely. I believe I have an idea on what the issue here is, but I can't find any information on how to resolve this in a batch file.
I do know on linux systems, if I were running a bash script to do something similar, I would want to have a & symbol at the end of each line to tell it to run the next command without waiting for the previous command to finish executing. I did try that in the batch script in the off chance that would work (It didn't).
For those who may ask, this is on Windows 8.1 64 bit. The user running this script is not an administrator.
I can't comment to expand on Squashman's suggestion, so let me answer here.
In your case, if you only want to have Pageant running in the background, without interacting with it, I think it's best to run:
START "" /B <your command>
The /B parameter will spawn the process without launching a new window for it, which seems like something you'd like to avoid (anyway, it's probably closest to the behaviour you can obtain in Linux with &).
Please note that if you close the window from which you spawned this process, it will terminate as well.

How to terminate only the inner batch job

Let's say there is some .bat file that is required to run inside .cmd batch script. This inner .bat file has a series of user interactions on a local host, and are only able to be ended using ctrl+c.
The question is: Is there some way to make the outer batch script resume after the inner script is terminated? Or is the ctrl+c the end all be all?
I've tried giving the inner script a different way out only to be told I'm not allowed to change that file. I've also done a fair amount of research and haven't found a solution. Forgive me if I've overlooked something! I'd like to avoid having two windows or extraneous termination messages pop up.
The only way I can think of to handle this is to use the following line in outer.cmd to call inner.bat -- with the disadvantage of receiving a new command prompt window for the execution of inner.bat:
start "" /WAIT cmd /C "inner.bat"
(Exchanging start and cmd does not work as the new window might unintentionally remain open.)
Note that for inner.bat, all the console input and output are handled via the new window, hence any redirections for outer.cmd (e. g., outer.cmd > "return.txt") will not include data from inner.bat.

Keep Windows command window open

I'm running a command through the Windows shell- an existing command window (cmd.exe). When I execute the command, the window closes, even though it's a freestanding window not tied to the command.
How can I keep the window open to see the output?
You can't simply start a child cmd session because it'll share same window and if your custom tool actively closes its window (I wonder why) then it'll close your console and output will disappear.
There isn't much you can do if a program want to close console window but you can at least save its output to a file (to be inspected later with type). If you're working with that console and you don't want to close it then you can use start cmd to execute it in a new console window. Like this:
start cmd /c tool -args ^> output.txt
tool output will be available in output.txt after it finished.
It appears that the executable is closing the command window. Here is what you could try, may work. open a command shell. In the shell issue "cmd" and open another command shell. Run your executable in the newly opened command shell. You nested cmd will be exited, but you may still be able to see some of the output of your executable.

Resources