问题描述:

StackOverflow threads have treated this topic before, but always in the context of writing code. I'm just trying to edit the registry.

I'm trying to create a context menu item on MP4 filetype. Sometimes I need to strip out the sound to an MP3, edit it with Audacity, and then put that back into the MP4. To do this I'm using DVDVideoSoft's FreeVideoToMP3Converter.exe. This app can convert multiple MP4s at a time. I can drag and drop them onto its window and have it open them all; executing a command line with multiple filenames uses one instance for all; and using SendTo opens multiple files in a single instance. What I can't seem to do is edit the MP4 filetype's context menu so that I can select multiple MP4 files and open them in a single instance. Research on StackOverflow and on the web indicates three approaches:

  1. Use MultiSelectModel=Player on the verb
  2. Use DDE
  3. Code a contextMenuHandler

3 does not apply, and 1 didn't produce the desired behavior. With 2, I'm guessing the trick is to figure out what the application name will be. Here's what I have at present (in Windows 10):

Windows Registry Editor Version 5.00

[HKEY_USERS\S-1-5-21-3229476284-161306217-3300585696-1001\SOFTWARE\Classes\AppX6eg8h5sxqq90pv53845wmnbewywdqq5h\Shell\ConverttoMP3]

@="Convert to MP3"

"MultiSelectModel"="Player"

[HKEY_USERS\S-1-5-21-3229476284-161306217-3300585696-1001\SOFTWARE\Classes\AppX6eg8h5sxqq90pv53845wmnbewywdqq5h\Shell\ConverttoMP3\command]

@="\"C:\\Program Files (x86)\\DVDVideoSoft\\Free Video to MP3 Converter\\FreeVideoToMP3Converter.exe\" \"%1\""

[HKEY_USERS\S-1-5-21-3229476284-161306217-3300585696-1001\SOFTWARE\Classes\AppX6eg8h5sxqq90pv53845wmnbewywdqq5h\Shell\ConverttoMP3\ddeexec]

@="Open(\"%1\")"

[HKEY_USERS\S-1-5-21-3229476284-161306217-3300585696-1001\SOFTWARE\Classes\AppX6eg8h5sxqq90pv53845wmnbewywdqq5h\Shell\ConverttoMP3\ddeexec\application]

@="FreeVideoToMP3Converter"

[HKEY_USERS\S-1-5-21-3229476284-161306217-3300585696-1001\SOFTWARE\Classes\AppX6eg8h5sxqq90pv53845wmnbewywdqq5h\Shell\ConverttoMP3\ddeexec\topic]

@="system"

Using the context menu on two selected MP4's results in the app opening one of them, and a messagebox from the other saying "There was a problem sending the command to the program." First guess is that's because I didn't get the DDE application name right.

Certainly I can use SendTo and get the desired result (and will be doing so while I wait for a response), but I'd like to get it right in the context menu, too. So my question is two-fold, both specific and general. First, how can I figure out what DDE will be using as an application name, so that I can specify it correctly? For example, Textpad's DDE application name is "Textpad.7", a string which appears nowhere else in the registry. How would one know that? One article said it is usually the filename with the ".exe" left off, but that's what I've got above, and, nope, not this time. And second, if I'm on the wrong track and need to head off in another direction, please point the way.

Previous StackOverflow threads on this topic said things like "it's not going to be as easy as you hope", but I can't help noting that SendTo does it, and without even a "%1". So what does SendTo know that I don't?

网友答案:

Made on Windows XP:

May also work on later versions of Windows.

Windows executes context menu item commands once for every selected file. I solved this problem by writing a .vbs script to concatenate arguments from all its instances and then call the application only once, with all file paths as arguments.

myscript.vbs:

set WshShell = WScript.CreateObject("WScript.Shell")
set WMIService = GetObject("winmgmts:root\cimv2")

dim FirstCommandLine, CommandLineParts, AllFiles

set AllInstances1 = WMIService.ExecQuery("Select CommandLine FROM Win32_Process WHERE CommandLine LIKE '%" & wscript.scriptname & "%'")
For Each item In AllInstances1
    FirstCommandLine = item.CommandLine 'Get the command line of the first instance of this script
    exit for
Next

if InStr(FirstCommandLine,WScript.Arguments.Unnamed(0)) then 'This is the first instance
    WScript.Sleep 400
    'Update instance list to check if other instances appeared
    set AllInstances2 = WMIService.ExecQuery("Select CommandLine FROM Win32_Process WHERE CommandLine LIKE '%" & wscript.scriptname & "%'")
    while AllInstances2.count > AllInstances1.count 'While other instances keep appearing
        WScript.Sleep 400
        'Keep updating instance list
        set AllInstances1 = AllInstances2
        set AllInstances2 = WMIService.ExecQuery("Select CommandLine FROM Win32_Process WHERE CommandLine LIKE '%" & wscript.scriptname & "%'")
    wend
    For Each item In AllInstances2
        CommandLineParts = Split(item.CommandLine,"""")
        AllFiles = AllFiles & """" & CommandLineParts(UBound(CommandLineParts)-1) & """ " 'Get all the file paths
    Next
    WshShell.Run("""Path\to your\application.exe"" /switches" & AllFiles)
else 'This is not the first instance. Before exiting, sleep for a moment for the first one to detect.
    WScript.Sleep 4000
end if

To make use of it you need to create a proper registry entry in HKEY_CLASSES_ROOT, with the following command:

wscript //nologo "Full Path\myscript.vbs" "%1"
相关阅读:
Top