marcusbuffett / pipe-rename

Rename your files using your favorite text editor
https://crates.io/crates/pipe-rename
MIT License
397 stars 12 forks source link

Doesn't seem to work with VSCode #76

Closed github-account1111 closed 1 year ago

github-account1111 commented 1 year ago
> O:\bin\pipe-rename-1-6-5-msvc.exe --editor code .\file1.jpg .\file2.txt
Error: Failed to execute editor command: 'code'

Caused by:
    program not found
mtimkovich commented 1 year ago

code is in your PATH, correct?

github-account1111 commented 1 year ago

Sorry for some reason I didn't get a notification for your reply.

It's in my PATH, yes, and I can launch VSCode by typing code in the terminal. image

This works but is inconvenient:

> O:\bin\pipe-rename-1-6-5-msvc.exe --editor --editor C:\\Program\ Files\\Microsoft\ VS\ Code\\Code.exe .\file1.jpg .\file2.txt
mtimkovich commented 1 year ago

I believe using code.cmd as the editor value should work.

This is the best explanation I could find as to why: https://github.com/Microsoft/vscode-docs/issues/1504#issuecomment-375205744.

Please let me know if that works.

assarbad commented 1 year ago

Being able to start something with foobar doesn't even mean that there is a foobar.exe. The PATHEXT environment variable is the responsible for completing the extension of any foobar you may try to execute. And that means .com comes before .exe -- which is why devenv.com (Visual Studio entry point application) exists as a console application that can be invoked without creating a window.

Other than that Execution Aliases exist since at least Windows 10. They are a special type of reparse point that allows to invoke store apps even though they are technically very segregated from the ordinary desktop apps. You can access it by Win+i and then searching for "alias" or "execution" or something along those lines for the language of your Windows. WinGet, Windows Terminal, WinDbg (Preview) and other store apps (including those using the desktop bridge) usually register Execution Aliases. Here's how that looks: image

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths and HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\App Paths are yet another place where "shorthands" to applications can be registered. Some of these may not work equally well with CreateProcess and ShellExecuteEx (or the older ShellExecute).


I took the liberty to install VSCode using:

>winget install -e --id Microsoft.VisualStudioCode

(ordinarily I use VSCodium as it's not phoning home) ... and the search for code yields:

>where code
C:\Users\Oliver\AppData\Local\Programs\Microsoft VS Code\bin\code
C:\Users\Oliver\AppData\Local\Programs\Microsoft VS Code\bin\code.cmd

I knew VSCodium employs a batch script named codium.cmd but didn't know for sure with VSCode. Now I do. You can even "see" it briefly if you invoke the Run dialog with Win+r and enter code and then hit Return. It'll at least briefly show a console window by default.

So no, @github-account1111, it is not in your PATH unless you added it there explicitly. Instead the subdirectory bin inside your VSCode installation directory is in your PATH if my system is anything to go by:

image

@github-account1111 please copy&paste the following into a text file and give it the .reg file extension, such as vscode.reg -- then double-click the saved file:

Windows Registry Editor Version 5.00

[-HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\App Paths\code.exe]

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\App Paths\code.exe]
@=hex(2):25,00,4c,00,4f,00,43,00,41,00,4c,00,41,00,50,00,50,00,44,00,41,00,54,\
  00,41,00,25,00,5c,00,50,00,72,00,6f,00,67,00,72,00,61,00,6d,00,73,00,5c,00,\
  4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,20,00,56,00,53,00,20,\
  00,43,00,6f,00,64,00,65,00,5c,00,63,00,6f,00,64,00,65,00,2e,00,65,00,78,00,\
  65,00,00,00
"Path"=hex(2):25,00,4c,00,4f,00,43,00,41,00,4c,00,41,00,50,00,50,00,44,00,41,\
  00,54,00,41,00,25,00,5c,00,50,00,72,00,6f,00,67,00,72,00,61,00,6d,00,73,00,\
  5c,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,20,00,56,00,53,\
  00,20,00,43,00,6f,00,64,00,65,00,00,00

This uses one of the mechanisms above to make code.exe truly available without adding it explicitly to the PATH. Not sure it'll work, but you could give it a shot. To make the same change globally, replace the HKEY_CURRENT_USER instances in the key names above with HKEY_LOCAL_MACHINE.

The .reg script first removes the subkey code.exe if it exists in that place (needed, because via regedit.exe it's hard to impossible to create a REG_EXPAND_SZ value) and then re-creates it, setting the default value and Path value to %LOCALAPPDATA%\Programs\Microsoft VS Code\code.exe and %LOCALAPPDATA%\Programs\Microsoft VS Code respectively.

PS: IIRC there are even more mechanisms for detouring the name of a program, such as Image File Execution Options. But the above were the likeliest for the case at hand. PPS: I tried the above .reg script and it worked. It won't work with a system-wide installer for VSCode (if these still exist). The paths would have to be adjusted there. But it would work for you with a user-local installer, since it uses a commonly available environment variable to point to the paths. And please don't ask me why the good folks who created VSCode (or VSCodium) don't use that method. It'd be so much more straightforward, I think.

assarbad commented 1 year ago

I believe using code.cmd as the editor value should work.

This is the best explanation I could find as to why: microsoft/vscode-docs#1504 (comment).

Please let me know if that works.

@mtimkovich It should, if the way renamer invokes the command is able to determine that .cmd needs the open verb to run with cmd.exe. So likely to work if Rust uses ShellExecute/ShellExecuteEx within this code, unlikely if it uses CreateProcess.

github-account1111 commented 1 year ago

I guess it almost worked.

> O:\bin\pipe-rename-1-6-5-msvc.exe --pretty-diff --editor code.cmd .\file1.jpg .\file2.jpg
Error: No replacements found

That error gets thrown immediately, and the file gets deleted right after being opened: image

mtimkovich commented 1 year ago
Usage: code.exe [options][paths...]

To read output from another program, append '-' (e.g. 'echo Hello World | code.exe -')

Try:

> O:\bin\pipe-rename-1-6-5-msvc.exe --pretty-diff --editor "code.cmd -" .\file1.jpg .\file2.jpg
assarbad commented 1 year ago

I guess it almost worked.

> O:\bin\pipe-rename-1-6-5-msvc.exe --pretty-diff --editor code.cmd .\file1.jpg .\file2.jpg
Error: No replacements found

That error gets thrown immediately, and the file gets deleted right after being opened: image

This makes perfect sense, because using the code.cmd renamer has no control of the child process. The child process code.exe is in fact a child process of the cmd.exe process that interprets the code.cmd. renamer waits for the process and keeps the temporary file open during that time.

I don't think the recommendation by @mtimkovich is going to change that.

Apologies, btw, my above method doesn't appear to work even with the .reg snippet. I'll have a look as to why and get back to you if I find it out.

Edit 1: changing the code.cmd file to add start /wait in front of the line executing code.exe also doesn't work for me. It should have fixed the issue with the waiting for the child process, though.

PS: registry files prepared for HKCU and HKLM: vscode-apppaths.zip

github-account1111 commented 1 year ago

Try:

> O:\bin\pipe-rename-1-6-5-msvc.exe --pretty-diff --editor "code.cmd -" .\file1.jpg .\file2.jpg

Thanks! This works. Quite unintuitive on M$' side but at least I don't have to hardcode the path.

assarbad commented 1 year ago

@mtimkovich could you explain the reasoning of how you came up with this. I understand that code.cmd - ought to read from stdin but how comes that renamer even uses stdin in this case?

I'm flabbergasted.

mtimkovich commented 1 year ago

uh I actually came up with this the "wrong" way. I was thinking that pipe-rename can take inputs from stdin for the files, so that's what was trying with code.cmd -. But that doesn't actually make sense because the input for the tool is different than the input for the editor.

It ended up working out though because VS Code uses the file as input for stdin if that's what's passed in and it also doesn't exit immediately like it normally would.