Command: Open file using extensions or mime-types to choose program

Hello,

I would like to share the script which I wrote. The idea is that I wanted to have a smart "open file" command which could automatically determine the type of a file (binary, text, image, e.t.c.) and choose an appropriate application for opening it.
I ended up using Unix "file" command to determine the MIME type of the file and use this information to distinguish which program should be used to open the file.

How it works
First the command checks the extension of the file and tries to find a match in the predefinedFileExtensions table. Then if there no match it runs file.exe command to find the MIME type of the file and then goes through the predefinedMimeTypes table trying to find the first regular expression matching the MIME type of the file. After getting a program it launches it and provides the file full name as the first parameter.

How to use (it is only one of the options)

  1. You need to have file.exe in your system. (for example, It is part of Git for Windows). Check that fileExe variable in the script points to the correct folder.
  2. copy paste the script file into the "Directory Opus"->Preferences->Scripts menu.
  3. "mouse right click on the toolbar"->Customize->Keys->"New Lister Hotkey".
  4. Fill in "UniversalOpen" in the "Function" field.

Source code (UnuiversalOpen.js)

var predefinedFileExtensions = [
    [ ["js", "txt", "log"],
      "%LOCALAPPDATA%/Programs/Microsoft VS Code/Code.exe" ],
    [ ["zip", "7z", "tar", "gz"],
      "%PROGRAMFILES%/7-Zip/7zFM.exe" ],
    [ ["lnk"],
      "C:/my/programs/Easy.Link.File.Viewer/Easy Link File Viewer.exe" ],
    [ ["msi"],
      "C:/my/programs/lessmsi/lessmsi-gui.exe" ],
    [ ["pdf"],
      "%ProgramData%/Microsoft/Windows/Start Menu/Programs/Acrobat Reader DC.lnk" ],
    [ ["exe", "dll"],
      "C:/my/programs/Dependencies/DependenciesGui.exe"]
]
var predefinedMimeTypes = [
    [ ["text\/.*"],
      "%LOCALAPPDATA%/Programs/Microsoft VS Code/Code.exe" ],
    [ ["image\/.*"],
      "C:/my/programs/iview/i_view64.exe" ]
]
var fileExe = "%PROGRAMFILES%/Git/usr/bin/file.exe"
var shell = new ActiveXObject("WScript.shell");

function OnInit(/* ScriptInitData */ data) {
    data.name = "Universal open"
    data.desc = "Open file using the most suitable application"
    data.default_enable = true
    data.config_desc = DOpus.NewMap()
    data.config.debug = false

    var cmd = data.AddCommand()
    cmd.name = "UniversalOpen"
    cmd.method = "onCommandExecuted"
    cmd.desc = data.desc
    cmd.label = data.desc
}

function onCommandExecuted(/* ScriptCommandData */ data) {
    var selectedFiles = data.func.sourcetab.selected_files
    debug("OnCommandExecuted: number of selected files = " + selectedFiles.Count)

    if (selectedFiles.Count != 1) {
        debug("Do nothing. This command works only when 1 file is selected")
        return
    }

    try {
        var selectedFile = getFirstElementOfCollection(selectedFiles)
        openFileUsingTheMostAppropriateProgramm(selectedFile)
    }
    catch (error) {
        var dlg = data.func.sourcetab.dlg
        dlg.message = error;
        dlg.buttons = "OK";
        dlg.icon = "error";
        dlg.show()
    }
}

function openFileUsingTheMostAppropriateProgramm(/* Item */ file)
{
    debug("openFileUsingTheMostAppropriateProgramm. File information: ext:'" + file.ext + "' realpath:'" + file.realpath + "'")

    var program = tryToFindProgramUsingExtension(file.ext)
    if(program)
    {
        launch(program, file.realpath)
        return
    }

    debug("Couldn't find a program using extension. Checking the mime type of the file")
    var mimeType = getFileMimeType(file.realpath)
    debug("mime type of the file is '" + mimeType + "'")

    program = tryToFindProgramUsingMimeType(mimeType)
    if(program)
    {
        launch(program, file.realpath)
        return
    }

    throw "No matching program found: extension='" + file.ext +"' mime-type='" + mimeType + "'"
}

function getFirstElementOfCollection(collection)
{
    var e = new Enumerator(collection)
    e.moveFirst()
    return e.item()
}

function tryToFindProgramUsingExtension(extension)
{
    for (var i = 0; i < predefinedFileExtensions.length; i++) {
        for(var j = 0; j < predefinedFileExtensions[i][0].length; j++) {
            if("." + predefinedFileExtensions[i][0][j] === extension) {
                return predefinedFileExtensions[i][1]
            }
        }
    }
    return null
}

function tryToFindProgramUsingMimeType(mimeType)
{
    for (var i = 0; i < predefinedMimeTypes.length; i++) {
        for(var j = 0; j < predefinedMimeTypes[i][0].length; j++) {
            if(new RegExp(predefinedMimeTypes[i][0][j]).test(mimeType)) {
                return predefinedMimeTypes[i][1]
            }
        }
    }
    return null
}

function getFileMimeType(fileFullName)
{
    var command = '"' + fileExe + '"' + ' --brief --mime-type "' + fileFullName + '"'
    debug("excecute: " + command)
    var res = shell.exec(command);
    if(res.ExitCode !== 0) {
        throw "Failed to execute the command. ExitCode=" + res.ExitCode
    }
    return res.StdOut.ReadAll().replace("\n", "")
}

function launch(executableFullName, fileFullName)
{
    var command = '"' + executableFullName + '" "' + fileFullName + '"'
    debug("launch: " + command)
    shell.run(command);
}

function debug(text) {
    if (Script.config.debug) {
        DOpus.Output(text);
    }
}

I have updated the script:

  • added an ability to run different applications depending on if .dll file is binary or managed code.
var predefinedFileExtensions = [
    [ ["zip", "7z", "tar", "gz"    ],    "%ProgramFiles%/7-Zip/7zFM.exe"                                                         ],
    [ ["lnk"                       ],    "C:/my/Programms/Easy.Link.File.Viewer/Easy Link File Viewer.exe"                       ],
    [ ["msi"                       ],    "C:/my/Programms/lessmsi/lessmsi-gui.exe"                                               ]]

var predefinedMimeTypes = [
    [ ["application\/pdf"          ],    "%ProgramData%/Microsoft/Windows/Start Menu/Programs/Adobe/Acrobat Reader DC.lnk"       ],
    [ ["text\/.*", "inode\/x-empty"],    "%LocalAppData%/Programs/Microsoft VS Code/Code.exe"                                    ],
    [ ["image\/.*"                 ],    "C:/my/Programms/iview/i_view64.exe"                                                    ],
    [ ["application\/x-dosexec"    ],    handleExeAndDllFiles                                                                    ]]

var fileExe = "%ProgramFiles%/Git/usr/bin/file.exe"
var shell = new ActiveXObject("WScript.shell");

function OnInit(/* ScriptInitData */ data) {
    data.name = "Universal open"
    data.desc = "Open file using the most suitable application"
    data.default_enable = true
    data.config_desc = DOpus.NewMap()
    data.config.debug = false

    var cmd = data.AddCommand()
    cmd.name = "UniversalOpen"
    cmd.method = "onCommandExecuted"
    cmd.desc = data.desc
    cmd.label = data.desc
}

function onCommandExecuted(/* ScriptCommandData */ data) {
    var selectedFiles = data.func.sourcetab.selected_files
    debug("OnCommandExecuted: number of selected files = " + selectedFiles.Count)

    if (selectedFiles.Count != 1) {
        debug("Do nothing. This command works only when 1 file is selected")
        return
    }

    try {
        var selectedFile = getFirstElementOfCollection(selectedFiles)
        openFileUsingTheMostAppropriateProgramm(selectedFile)
    }
    catch (error) {
        var dlg = data.func.sourcetab.dlg
        dlg.message = error;
        dlg.buttons = "OK";
        dlg.icon = "error";
        dlg.show()
    }
}

function openFileUsingTheMostAppropriateProgramm(/* Item */ file) {
    debug("openFileUsingTheMostAppropriateProgramm. File information: ext:'" + file.ext + "' realpath:'" + file.realpath + "'")

    var program = tryToFindProgramUsingExtension(file.ext)
    if(program) {
        launchProgram(program, file)
        return
    }

    debug("Couldn't find a program using extension. Checking the mime type of the file")
    var mimeType = getFileMimeType(file.realpath)
    debug("mime type of the file is '" + mimeType + "'")

    program = tryToFindProgramUsingMimeType(mimeType)
    if(program)
    {
        launchProgram(program, file)
        return
    }

    throw "No matching program found: extension='" + file.ext +"' mime-type='" + mimeType + "'"
}

function launchProgram(program, file)
{
    if (typeof program === 'function') {
        program(file.realpath)
        return
    }
    launch(program, file.realpath)
}

function getFirstElementOfCollection(collection)
{
    var e = new Enumerator(collection)
    e.moveFirst()
    return e.item()
}

function tryToFindProgramUsingExtension(extension)
{
    for (var i = 0; i < predefinedFileExtensions.length; i++) {
        for(var j = 0; j < predefinedFileExtensions[i][0].length; j++) {
            if("." + predefinedFileExtensions[i][0][j] === extension) {
                return predefinedFileExtensions[i][1]
            }
        }
    }
    return null
}

function tryToFindProgramUsingMimeType(mimeType)
{
    for (var i = 0; i < predefinedMimeTypes.length; i++) {
        for(var j = 0; j < predefinedMimeTypes[i][0].length; j++) {
            if(new RegExp(predefinedMimeTypes[i][0][j]).test(mimeType)) {
                return predefinedMimeTypes[i][1]
            }
        }
    }
    return null
}

function getFileMimeType(fileFullName)
{
    var command = '"' + fileExe + '"' + ' --brief --mime-type "' + fileFullName + '"'
    debug("shell.exec " + command)
    var res = shell.exec(command);
    if(res.ExitCode !== 0) {
        throw "Failed to execute the command. ExitCode=" + res.ExitCode
    }
    return res.StdOut.ReadAll().replace("\n", "")
}

function handleExeAndDllFiles(exeOrDllFile)
{
    if(isManagedExeOrDll(exeOrDllFile) === true) {
        launch("%AppData%/Microsoft/Windows/Start Menu/Programs/JetBrains/JetBrains dotPeek 2021.3.2.lnk", exeOrDllFile)
        return
    }
    launch("C:/my/Programms/Dependencies/DependenciesGui.exe", exeOrDllFile)
}

function isManagedExeOrDll(exeOrDllFileFullName)
{
    var command = "powershell.exe -ExecutionPolicy Bypass -Command [System.Reflection.AssemblyName]::GetAssemblyName(\\\"" + exeOrDllFileFullName + "\\\")"
    debug("excecute: " + command)
    var res = shell.run(command, 0, true);
    return res === 0;
}

function launch(executableFullName, fileFullName)
{
    var command = '"' + executableFullName + '" "' + fileFullName + '"'
    debug("launch: " + command)
    shell.run(command);
}

function debug(text) {
    if (Script.config.debug) {
        DOpus.Output(text);
    }
}

After adding a script, failure is displayed in the script options