start /wait fails to wait if file already open - ruby

system( "start /wait file.docx")
This starts the file but fails to wait if another docx file already open. Works perfectly if there is no file open.
What I am trying to do : I would like to open a file in windows with its default editor and wait for the user to input and do some changes to the file post save, hence I am using
/wait.
Thanks for any tip?

The default behaviour in winword is to reuse existing instances of the executable to open multiple documents. So, the second open file operation delegates its work into the existing one and exits, so the start command returns.
One usual option is to use COM to open the file and test for closing of the instance. But i know nothing of ruby or if it supports COM.
The best approach will be locate the winword executable and call it directly using as paramenters /w filename.docx to force opening the file into a new instance.

Related

CMD doesn't wait to finish process

When i use command
<path exc.xlsx>
it starts excel file working and wait until i close the file than i can type next command. My issue is that when other excel file is running cmd doesn't wait to close the file and goes to next line. It is necessary to type the command that will force cmd to wait until i close excel file even when onother excel file is running. I tried a lot of commands from the internet but no one seems to work properly. These were for instance:
start /wait exc.xlsx && exit
exc.xlsx cmd /k
exc.xlsx|rem
I'm using Windows7.
I try this method but it sometimes doesn't work properly. The line <os.rename> try to change name of the file. If it can it means that the file is closed and break the loop but using that the script sometimes can't open the excel file. I'm not as advanced as i would be and cant find another way to check if the file is closed.
import os
def is_open(file_name):
if os.path.exists(file_name):
while True:
try:
os.rename(file_name, file_name)
break
except:
continue
time.sleep(0.001)
is_open('exc.xlsx')
That's not very dignified and uses a lot of processor. If there is a way using programing language (preferably python) I can implement that in my script.

Coding a Delphi GUI utility for use in a CMD window

I'm writing myself a GUI utility for use in a CMD window to navigate between folders,
rather in the style of the old Norton Change Directory utility for DOS.
When run, the app pops up a folder tree to allow the user to select a folder to which
to navigate and then closes and returns to the CMD prompt. At the moment, the way it
works is that it is run as the first command in a "main" batch file. It writes a secondary batch
file, in my app's folder under AppData, containing the commands to change drive and
directory to the folder the user selected, and the main batch file then invokes this
second batch file using CALL.
It works fine, but this way of actually changing the CMD window's current directory
strikes me as inelegant both from the point of view of needing to be run from a batch file
(so that the user's selection can be acted upon after my app has closed) and of
needing the secondary batch file to do the actual navigation.
So, my question is, how can my app send the instructions to the instance of CMD
that owns the window in which the app is run to the folder the user selected? I've tried doing a ShellExecute
of "CMD /K ..." but although that does indeed navigate to the
selected folder, it does so in a new CMD window, not the one my app is run in. The
conceptual gap I have is how to get the current CMD to act on my app's instructions
after my app has terminated.
Fwiw, I thought of trying to write the user's folder selection into an environment variable in the CMD window's environment for the CMD processor to
act upon from there, but this seems to require that the CMD window be opened via "Run as Administrator", which I definitely don't want.
Your program cannot influence the environment variables of the command interpreter because they're separate processes. Your program cannot change the directory of the command interpreter directly, either, because, again, they're separate processes.
You need to use a batch file because the command interpreter executes batch files internally. Since it's all the same process, the batch file has the power to change the current directory, and for that change to remain in effect after the batch file finishes running.
Therefore, you need some way for your interactive program to communicate the directory selection back to the batch file so that it can act on it.
Instead of writing the instructions to another batch file, you could write the result to standard output. Have the batch file capture that output into a variable, and then execute cd on that variable. The batch code would look something like this:
for /f "tokens=*" %%a in ('[select_dir.exe]') do (
set DIRSELECTION=%%a
)
cd /d %DIRSELECTION%
Your Delphi code would look like this:
writeln(selected_dir);
To allow that command to work, you'll need to make sure your program is marked as a console program, as with {$APPTYPE CONSOLE}. If it's not, then the batch file won't receive any output, and probably won't even wait for your program to finish running before proceeding. It's OK for a console program to display a TForm, just like a GUI program.

Automatic encryption/decryption: detect file is closed in Mate/Gnome application

I'm writing a bash script to automatically decrypt file for editing and encrypt it back after file is closed. File type could be any: plain-text, office document, etc. I am on Linux Mint with Mate.
I'm stuck: can't reliably detect if file was closed in application so that script can proceed to encrypting it back and removing decrypted version.
The first version of the script simply used vim with text files. Script was calling it directly and hadn't been going any further until vim was closed. Now as I want to be able to do so with other files, I tried the following things:
xdg-open: exits immediately after calling the application associated with file type. Thus script continues and does no good.
xdg-open's modified function for calling an associated app: runs it inside the current script so now I see program exit. Works only if the application hasn't been running already. If it has, then new process is finished and script continues.
So what I am trying to do now is to watch somehow that file was closed in already running application. Currently experimenting with pluma/gedit and inotifywait. It doesn't work either - instantly after file was opened it detects CLOSE_NOWRITE,CLOSE event.
Is it at all possible to detect this without specific hooks for different applications? Possibly some X hooks?
Thank you.
You could use lsof to determine if a file is opened by a process:
myFile="/home/myUser/myFile"
/usr/sbin/lsof "$myFile" | grep "$myFile"
You can use a 1 second loop and wait until the lsof response is empty. I have used this to help prevent a script from opening a newly discovered file that is still being written or downloaded.
Not all processes hold a file open while they are using it. For example, vim holds open a temporary file (/home/myUser/.myFile.swp) and may only open the real file when loading or saving.
You might do something like this.
decrypt "TheFile"&
pluma "TheFile"
encrypt "TheFile"
The & at the end of a line will execute the line then fall through to Pluma. The script will pause until pluma closes.
I could offer more help if you post your script.

Run an arbitrary file as a windows bat file from Firefox?

Say I've got a windows batch file with a file extension .batscript, and say I've got a web server set up to serve it with a content-type of application/x-batscript. How can I set up Firefox 4 to "always open" this file so that it runs as a standard batch file would? (I have access to the PCs but want avoid creating/installing external programs/extensions/plugins)
I can't use a straight .bat because Firefox doesn't allow those to be opened directly; they have to be saved and run separately (for obvious security reasons).
The standard way to run a batch file is cmd /c %1 where %1 is the path to the bat file, but this doesn't work when %1 is a path to a file with a custom file extension (such as .batscript) because cmd looks up what application %1 should be opened with, so adding a direct file association via the registry doesn't work (it recursively opens cmd prompts).
Instead, I found a work around where I temporarily copy my .batscript file to a .bat file and run it, using registry entries like this, which allows me to double click on a .batscript file to run it. But Firefox doesn't respect these platform file associations!
Ok, so Firefox wants me to define my file type associations separately for each content-type: fair enough, file extensions & content-types aren't always the same. But I can only get Firefox to run discrete applications, and a batch script needs to be run with cmd.exe /c %1 not just cmd %1.
Does anybody know of a way to force Firefox to either use the system file association or allow launching arbitrary programs with command line parameters?
(For those wondering, the use case is similar to "an internal web app which allows users to run a local program with a varying amount of command line parameters by clicking on a link" - alternative solutions to these small "breaking out of the sandbox" problems are also welcome!)
I think you need to edit the MimeTypes.rdf file. For more information see also this page.

What is the simplest program I can write to invoke a batch script?

It is very stupid that windows will not let you add batch files to your quick launch or whatever they call in in windows 7. That bar across the bar, i can attach firefox there, command prompt, even paint (my favorite), but not a batch file. I can "pin" it to another program, which is just weird. I want it to standalone, the batch file does enough work by itself.
So lets say i have batch file. What is the simplest executable program I can write to invoke said script. Then I can finally pin all my useful batch files on that quick-jump-pin-bar.
If I remember right, you can do this by first pinning a shortcut to CMD.exe to the taskbar. Then edit the command, and change CMD.exe to CMD.exe /c MyBatchFile.bat. I believe this will execute the batch file.
Since you can only pin one cmd, here's an alternative, assuming you have the .NET framework installed - a very simple C# application:
Populate a textfile with the following contents:
class Program {
static void Main() {
System.Diagnostics.Process.Start(#"c:\test.bat");
}
}
where Program is the name of the executable you want to create, and c:\test.bat is the full path to the batch file. Save the file as Program.cs. Execute the following from the command line:
c:\Windows\Microsoft.NET\Framework\v2.0.50727\csc.exe Program.cs
You can replace 2.0.50727 with whatever directory exists on your machine - might be 1.1.something or 3.5 or 4.0.something - it's all the same for this scenario.
This will generate Program.exe. You can put that exe file wherever you want, and pin that executable to the taskbar. You can discard the .cs file once you're done making your executables.
Kind of a crappy solution, but it should work, assuming you don't find anything better. And if you don't have the .NET framework (which I'm not sure is even possible in Windows 7), you can install it pretty easily.
The easiest way is to create a folder, put your batch files in it, and pin the folder to the menu bar :D
You can also write a startup script, so the batch file will be executed on startup, but I don't know if you want to run those scripts on every bootup... You can also add the command prompt to the bar, and edit the startup path..
Use command switches on CMD.exe.
cmd.exe /c "myscript.bat"
As a sort of workaround you could use the following trick. Pin an arbitrary application to the task bar, Shift+right click on the pinned icon, select Properties, change 'Target' and 'Start in' accordingly. Rename it too if you like.
You can pin more than one .bat file using this technique.

Resources