Short version:
On Windows, if I select several .txt files in a File Explorer and then right click on one of the selected files and choose "Open" from the popup menu, all of the selected files will be opened, each in a separate instance of Notepad.
I want the same behavior for our files/editor: select multiple output files, right click one, select Open: -> all files are opened, each in their own instance of our editor.
I have basic click-to-open working (for a single file, double click opens the file in our editor, right click and Open does the same).
Details
We have an launcher (FuBarStudioLauncher.exe) that updates then launches our editor tool (FuBarStudio.exe), which produces resource files with a custom extension (samplefile.fbr)
If you run from the command line, you can fire up the editor, opening a particular resource:
C:\path_to_my_exe\FuBarStudio.exe" -ide samplefile.fbr
I have a windows registry entry set up so that when I double click on a *.fbr resource file, or right-click and select Open from the popup menu, the launcher runs, passing the given resource through to the editor.
The relevant registry entries:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\.fbr]
#="FuBar.Place"
[HKEY_CLASSES_ROOT\.fbr\FuBar.Place]
[HKEY_CLASSES_ROOT\.fbr\FuBar.Place\ShellNew]
and
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\FuBar.Place]
#="FuBar Place"
[HKEY_CLASSES_ROOT\FuBar.Place\shell]
[HKEY_CLASSES_ROOT\FuBar.Place\shell\Open]
#="Open"
[HKEY_CLASSES_ROOT\FuBar.Place\shell\Open\command]
#="\"C:\\path_to_my_exe\\FuBarStudioLauncher.exe\" -ide \"%1\""
All of this works fine for single files.
If I select more than one .fbr file and then right click one of the selected files and select "Open", I will only open one instance of FuBar Studio.
I would like to open one Copy of FuBar Studio, one for each file.
So with some help I got a useful answer.
1) I read up on use of MultiSelectModel here:
https://msdn.microsoft.com/en-us/library/windows/desktop/hh127436(v=vs.85).aspx
Set my type to Document.
2) I created a batch script as an intermediary, so I could see better what was going on:
[HKEY_CLASSES_ROOT\FuBar.Place\shell\Open\command]
#="\"C:\\path_to_my_exe\\launcher.bat\" \"%1\""
Toyed around with this script, writing things to tmp files:
echo "interesting things" >> logs.txt
and using timeout to force things to pause/slow down:
timeout 10
Using "echo" and so forth I realized that whether MultiSelectModel is set to Document or Player, when I select multiple files and right click "Open", Windows is executing the business at:
HKEY_CLASSES_ROOT\FuBar.Place\shell\Open\command
once per selected file.
I could not find a way to force Windows to call the command once, passing all the files as arguments to the command.
3) By experimenting with other programs besides my own, and with the script + timeouts giving me a command shell with error spew to look at, I realized that my particular program, FuBarStudioLauncher.exe, always fails if another instance is running.
So here's what I have:
Windows is going to run one instance of <something> per input file.
<something> can't be my FuBarStudioLauncher.exe, because after one is running the next N will fail.
So I need an intermediary script that will do some kind of critical section locking:
- grab lock.
- run launcher to completion.
- release lock.
Hooray for StackOverflow:
Semaphore for CMD instances working in Parallel
Using this as input, my final product:
:lockedAppend
2>nul (
>>%~dp0launcher_script_lockfile.txt (
REM Do any amount of processing within this block.
REM All stdout will safely be appended to the queue
REM You could even call out to a subroutine, or another batch file
%~dp0FuBarStudioLauncher.exe -ide "%1"
REM The CALL below ensures that the block exits with ERRORLEVEL 0 - success
(call )
)
) || goto :lockedAppend
That did it!
Related
nvidia-smi executed in a Command Prompt (CMD) in Windows returns the following error
C:\Users>nvidia-smi
'nvidia-smi' is not recognized as an internal or external command,
operable program or batch file.
Where is it located? CUDA is installed already.
Nvidia-SMI is stored by default in the following location
C:\Windows\System32\DriverStore\FileRepository\nvdm*\nvidia-smi.exe
Where nvdm* is a directory that starts with nvdm and has an unknown number of characters after it.
Note: Older installs may have it in C:\Program Files\NVIDIA Corporation\NVSMI
You can move to that directory and then run nvidia-smi from there. However, the command prompt window will not persist, making it very difficult to see the information. Additionally it is challenging to determine what the nvdm* directory is as this changes and there are multiple directories of this format. To complicate matters, unlike linux, it can't be executed by the command line in a different path. It's better to find the exact location and create a shortcut that runs it in a periodic manner.
To find your exact location
Open File Explorer (File Folder Icon on your Task Bar, Near Start / Cortana / Task View buttons).
In the left Pane, click 'This PC'.
In the main viewer, just to the top of the Icons, is a search bar. Type nvidia-smi.exe and hit enter. It will come up after some time.
Right-click and choose 'Open File Location' and continue with the below instructions to make a desktop shortcut, or double click to run once (not recommended, as it runs and closes the window once complete, making it hard to see the information).
Make a shortcut that runs nvidia-smi and refreshes periodically
Follow the above steps under 'To find your exact location'.
Right click on nvidia-smi.exe (it may just say nvidia-smi in the viewpane) and choose create a shortcut. It will likely tell you that you can't create a shortcut here, and ask if you want to put it on your desktop. Hit yes.
Now, on the desktop, right click on the shortcut you have just created, hit properties, and Under Shortcut > Target modify the string path to include -l < time you want it to refresh >.
For example, modify:
C:\Windows\System32\DriverStore\FileRepository\nvdm*\nvidia-smi.exe
to
C:\Windows\System32\DriverStore\FileRepository\nvdm*\nvidia-smi.exe -l 5
Then hit "Apply", and then "OK".
In this example, when you open the shortcut, it will keep the command prompt open and allow you to watch your work as nvidia-smi refreshes every five seconds.
You can add "C:\Program Files\NVIDIA Corporation\NVSMI" to PATH and than restart console.
System Properties > Advanced > Environment Variables > System Variables -> Path -> Edit > New > insert folder path with nvidia-smi
On my Windows 10 machine installed with CUDA 10.2, nvidia-smi.exe can be found at C:\Windows\System32.
Because C:\Windows\System32 is already in the windows PATH, running nvidia-smi in command prompt should now work out of the box
Go to the file explore then go to the C drive in the search bar type nvidia-smi
Wait sometimes when exe file is open right click go to the properties copy the location path
Then go to the anaconda command prompt change the working directory by using the copy path in step 2
Then write "nvidia-smi" hit enter
Click Here for more information
On Windows, you can use the Power Shell and type nvidia-smi -l 1 to GPU summary every 1 second, or nvidia-smi -lms every millisecond. Don't forget to add the CUDA environment files to PATH, as mentioned in the above suggestions.
You can try to write a .bat file for a one-click operation later.
ECHO Open folder
::my nvidia-smi folder (nvidia-smi.exe can be found on two different folders, either is ok)
cd /d c:\Program Files\NVIDIA Corporation\NVSMI
::cd /d c:\Windows\System32\DriverStore\FileRepository\nvami.inf_amd64_42b7e5f6a9e28f81
ECHO NVIDIA-SMI
::use `-l < time you want it to refresh >` to keep window
call nvidia-smi.exe -l 3
reference to #Hewston, the aforementioned script can be further simplified as follows:
::ECHO Open folder
::add my nvidia-smi folder to PATH variable
::cd /d c:\Program Files\NVIDIA Corporation\NVSMI
ECHO NVIDIA-SMI
::use `-l < time you want it to refresh >` to keep window
call nvidia-smi.exe -l 5
Here's the situation, every time I need to do the step below after I boot my computer:
Open the cmd(admin)
copy this cmd into cmd:
C:\Windows\system32\netsh int ipv4 set glob defaultcurhoplimit=65
enter
For now, I hope to double click a file that can directly execute the command above without the step above.
Any method?
You can save it to .bat or .cmd file and run it on double-click.
Create a file with any name and extension .bat I.g. setLimit.bat. I assume you know how to create files.
Open file from above step in file editor, i.g. notepad.exe. Copy and paste line C:\Windows\system32\netsh int ipv4 set glob defaultcurhoplimit=65 into the file and press Ctrl+S to safe it. I hope it makes sense otherwise ask.
Double click on the file to execute the command.
If you need to run it under elevated privilege (i.e. admin) right click on file and choose Run as administrator option in menu.
You need a .bat file to execute the command and a shortcut to have it executed as administrator.
Creating the .bat file is trivial: use you favorite text editor (or notepad), type the command, optionnaly add a line PAUSE if you want to see eventual messages and save it to disk with a .bat extension (say c:\...\sethoplimit.bat)
Creating the shortcut is not much harder: right click on desktop, Create new..., Shortcut, and just select the newly created file
The magic comes now: right click on the newly created shortcut and click Properties, in Shortcut tab, click the Advanced button and select Execute as admin.
That's all. Each time you double click on the shortcut, Windows will start a console with elevated priviledges, eventually open the User Account Control confirmation dialog, and execute the batch file as administrator.
Here I showed you how to create the shortcut directly on the Desktop, but the same process can be used for a shortcut anywhere on a disk folder.
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.
I run batch files and they exit immediately. I dont want that to happen so that i can see my output. Can someone tell me how to make this happen ?
I use windows 7.
Put this on the very last line of the Batch:
cmd /k
Adding pause is a good answer. Here are some other ways as well..
Rather than double-clicking on them to execute you can run from a command line:
Press the windows key + r (this opens the "run" window)
Type: cmd into the text input and press enter (or click ok)
Change to the directory that contains the batch file, e.g: cd c:\scripts\foo
Execute the batch file by typing it's name and pressing enter, e.g: somename.bat
If there is a lot of output and it scrolls off the screen you can direct the output to a text file instead like so:
somename.bat > output_filename.txt
Then you can open the 'output_filename.txt' file in any text editor to view/search all of the output. This is better than pause when there more output than what is available in the scrollback.
Add the pause command at the end of your batch file. This waits for you to key something in.
(The nice thing is that if you're running the batch file from a non-interactive process, such as a automated build system or scheduled task, the pause is simply skipped.)
The help message for pause is:
C:\>help pause
Suspends processing of a batch program and displays the message
Press any key to continue . . .
If there is lots of output and you can't scroll far enough back, adjust the screen buffer height of the command window. This can be done via right-click on the c:\ icon go to properties -> layout:
What I want to do is very simple, yet can't find the way to do it.
In my projects I have several .bat files (I know, I'm old) the perform some tasks like running SqlMetal, etc.
I just want to right-click the file and select "run" or something so the bat is executed. How do I do it?
Note: I know I can use Tools -> External Tools, but it's not what I'm looking for
If each project has a few batch files associated with it then why not include them in the project and add a new external tool and link it with a custom menu item to run the tool? This will give you a list of batch files in each project and a context menu command to run them. The only downside is that it isn't file type specific (it will let you run any file as a batch file).
Here's how to do it...
Create an external tool called "Run batch file"
Set the Command to: CMD.EXE
Set the Arguments to: /c "$(ItemPath)"
Set the Initial directory to: $(ItemDir)
Check the "use output window" checkbox and then Apply to create the command
Note where the new command appeared in the list of commands. The external commands are numbered from 1 starting below the divider bar. #1 is usually "Create GUID"
Now go to Tools -> Customize and select the commands tab.
Select the Context menu radio button and select "Project and Solution Context menus | Item" from the dropdown.
Now use "Add Command..." to add a new command
In the Categories list select "Tools"
From the commands select the "External Command #" that corresponds to the position of the "Run Batch file" custom command you noted the number of in step 5 above.
Move it to the correct position in the list add keyboard shortcuts etc.
Close the dialog.
Now right click on the batch file and you should see a "Run batch file" menu item. This will execute the batch file and show its output in the VS Output window.
Right click the batch file in the Solution Explorer
Select “Open With…” from the context menu
Click “Add…”
In the “Program name” textbox, enter powershell.exe
In the “Friendly name” textbox enter “PowerShell”
Select “Set As Default”
Click OK
via
Check out the Open Command Line Visual Studio extension.
As per the description, it features:
Opening of a command line at the root of the project.
Support for all consoles such as CMD, PowerShell, Bash etc.
Syntax highlighting, Intellisense and execution of .cmd and .bat files.
For files in your solution, a context-menu button shows up.
Alternatively, the keyboard shortcut Shift+Alt+5 can be used when editing a batch file. This makes it really easy and fast to execute any batch file - even ones that are not part of your project.
Right-click a file in the Solution Explorer window, Open With, click the Add button to add your .bat files. Use %1 in your .bat to get the path to the selected file.
Couldn't get any of the above to quite work, but this did (VS 2019/2022):
Right click a .bat file in Solution Explorer and Open With...
Add...
Program: CMD.exe
Arguments: /c %1
Friendly name: Command
OK and Set as Default for double clicking of batch files to run from Solution Explorer as the default (or right click Open With... and select Command if you don't want it the default).
Merely a suggestion: This is a scenario which can be done with the VsCommandBuddy extension. The following configuration is an example:
{
"cmdname": "mk",
"title": "Run MK.BAT",
"description": "Run the MK bat file.",
"cwd": "$(SolutionDir)",
"filename": "cmd.exe",
"arguments": "/C mk.bat",
"async": false
}
You can assign shortkeys as well, so you can invoke your batch files with shortcut keys. Output comes in your output pane.