2

On Windows, if you right click a file in explorer, you get a context menu. One of the entries is Open With > Choose another program. Clicking this opens a GUI to choose a program to open the file. Is it possible to open this GUI from the command line?

Jonathan Seaman
  • 142
  • 3
  • 6
  • Typically, all you would really need to do is point to the location of the program, followed by the path of whatever you want to open. So something like: `notepad.exe c:\file.txt`, or using `Start-Process` (*or just `start`*): `Start-Process "C:\VS Code\Code.exe" "c:\useres\abe\dt\file.ps1"`. You can also do the same with the *invocation* / *call* operator (`&`). – Abraham Zinala Jan 02 '22 at 02:34
  • Thanks. I didn't know about the call operator. – Jonathan Seaman Jan 02 '22 at 07:51
  • I am using obsidian.md to manage notes and am interested in having a context menu in the app that can open the "Open with" dialog. The easiest way to do it would be with a command line call. It would allow me to open the same file with different programs as convenient. – Jonathan Seaman Jan 02 '22 at 07:56
  • This reads like the problem you are trying to solve the what you have asked for aren't the same thing. This is commonly known as the [XY Problem](http://xyproblem.info). – IInspectable Jan 02 '22 at 09:14

1 Answers1

6

There is a shell API for this purpose that can be used from PowerShell using P/Invoke. This is more reliable than the often suggested but undocumented "RunDll32.exe OpenAs_RunDLL" method (see this answer for details why it is bad).

Save this code as "openas.ps1":

param (
    [Parameter(Mandatory)]
    [String] $Path
)

$ErrorActionPreference = 'Stop'

Add-Type -TypeDefinition @'

    using System;
    using System.Runtime.InteropServices;

    public class ShellOpenWith {

        [DllImport("shell32.dll", EntryPoint = "SHOpenWithDialog", CharSet = CharSet.Unicode)]
        private static extern int SHOpenWithDialog(IntPtr hWndParent, ref tagOPENASINFO oOAI);

        // http://msdn.microsoft.com/en-us/library/windows/desktop/bb773363(v=vs.85).aspx
        private struct tagOPENASINFO
        {
            [MarshalAs(UnmanagedType.LPWStr)]
            public string cszFile;

            [MarshalAs(UnmanagedType.LPWStr)]
            public string cszClass;

            [MarshalAs(UnmanagedType.I4)]
            public tagOPEN_AS_INFO_FLAGS oaifInFlags;
        }

        [Flags]
        private enum tagOPEN_AS_INFO_FLAGS
        {
            OAIF_ALLOW_REGISTRATION =  0x00000001,   // Show "Always" checkbox
            OAIF_REGISTER_EXT =    0x00000002,   // Perform registration when user hits OK
            OAIF_EXEC =        0x00000004,   // Exec file after registering
            OAIF_FORCE_REGISTRATION =  0x00000008,   // Force the checkbox to be registration
            OAIF_HIDE_REGISTRATION =   0x00000020,   // Vista+: Hide the "always use this file" checkbox
            OAIF_URL_PROTOCOL =    0x00000040,   // Vista+: cszFile is actually a URI scheme; show handlers for that scheme
            OAIF_FILE_IS_URI =     0x00000080    // Win8+: The location pointed to by the pcszFile parameter is given as a URI
        }

        public static void DoOpenFileWith(string sFilename, IntPtr hwndParent = new IntPtr())
        {
            tagOPENASINFO oOAI = new tagOPENASINFO();
            oOAI.cszFile = sFilename;
            oOAI.cszClass = String.Empty;
            oOAI.oaifInFlags = tagOPEN_AS_INFO_FLAGS.OAIF_ALLOW_REGISTRATION | tagOPEN_AS_INFO_FLAGS.OAIF_EXEC;
            SHOpenWithDialog(hwndParent, ref oOAI);
        }    
    }
'@

[ShellOpenWith]::DoOpenFileWith( $path )

Run this script from the commandline like this:

powershell.exe c:\openas.ps1 c:\file.txt
zett42
  • 25,437
  • 3
  • 35
  • 72
  • 1
    "Run Always" button doesn't show on my machine. – SleepyBag Feb 06 '23 at 11:19
  • 1
    @SleepyBag From the [docs](https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shopenwithdialog): _"Starting in Windows 10, the OAIF_ALLOW_REGISTRATION, OAIF_FORCE_REGISTRATION, and OAIF_HIDE_REGISTRATION flags will be ignored by SHOpenWithDialog. The Open With dialog box can no longer be used to change the default program used to open a file extension. You can only use SHOpenWithDialog to open a single file."_ – zett42 Feb 06 '23 at 12:09
  • @SleepyBag An alternative might be `Start-Process -Verb openas -FilePath MyFileName`. I have noticed a strange behavior though: After setting the default application for a completely new file extension ".foo42" by selecting "Run Always", calling `Start-Process` a 2nd time fails with error "The specified file does not have an associated application." – zett42 Feb 06 '23 at 22:05