Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to get file type association in Windows 10 from command line?

I am aware that I can use assoc and ftype on the command line to get the file type assocation. So when i do:

enter image description here

I am under the impression that .html files are opened with iexplorer.

However html files are opening with chrome since chrome has been set as the default app for html files.

enter image description here

Why is ftype giving me iexplorer when indeed the program opens with chrome?

like image 765
Postlagerkarte Avatar asked Aug 06 '18 20:08

Postlagerkarte


2 Answers

It seems that ftype and assoc are pretty useless on systems running Windows 8 or later.

This is due to the fact that Microsoft decided in Windows 8 that users should be able to set default programs only via the built in GUI. This probably was due to security reasons and trouble with applications hijacking file type associations.

Therefore a new registry key was introduced and Windows now writes the user choice to

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\<extension>\UserChoice

The key contains a Prog-Id and a Hash Value. The correct Hash value proves that the UserChoice ProgId value was set by the user, and not by any other application. If the hash is invalid, windows will reset the user choice to the default application.

The ftype command however is not aware of the above registry key.

It reads the HKCR\htmlfile\shell\open\command\(Default) registry key and prints out the result.

Therefore the results of the ftype command therefore are not usuable to determine which application is associated with a specific file extension.

like image 51
Postlagerkarte Avatar answered Nov 09 '22 23:11

Postlagerkarte


As mentioned by Eryk Sun, you can get it with AssocQueryString. Here's a powershell implementation as he mentioned mostly derived from this: http://pinvoke.net/default.aspx/shlwapi.AssocQueryString

$Signature = @"
using System;
using System.Runtime.InteropServices;
using System.Text;
    public static class Win32Api
    {

        [DllImport("Shlwapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
        static extern uint AssocQueryString(AssocF flags, AssocStr str, string pszAssoc, string pszExtra,[Out] System.Text.StringBuilder pszOut, ref uint pcchOut);


        public static string AssocQueryString(string extension)
        {
            return AssocQueryString(AssocF.None, AssocStr.Executable, extension);
        }

        internal static string AssocQueryString(AssocF assocF, AssocStr association, string assocString)
        {
            uint length = 0;
            uint ret = AssocQueryString(assocF, association, assocString, null, null, ref length);
            if (ret != 1) //expected S_FALSE
            {
                return null;
                //throw new InvalidOperationException("Could not determine associated string");
            }

            var sb = new System.Text.StringBuilder((int) length); //(length-1) will probably work too as null termination is added
            ret = AssocQueryString(assocF, association, assocString, null, sb, ref length);
            if (ret != 0) //expected S_OK
            {
                return null;
                //throw new InvalidOperationException("Could not determine associated string");
            }

            return sb.ToString();
        }


        [Flags]
        internal enum AssocF : uint
        {
            None = 0,
            Init_NoRemapCLSID = 0x1,
            Init_ByExeName = 0x2,
            Open_ByExeName = 0x2,
            Init_DefaultToStar = 0x4,
            Init_DefaultToFolder = 0x8,
            NoUserSettings = 0x10,
            NoTruncate = 0x20,
            Verify = 0x40,
            RemapRunDll = 0x80,
            NoFixUps = 0x100,
            IgnoreBaseClass = 0x200,
            Init_IgnoreUnknown = 0x400,
            Init_FixedProgId = 0x800,
            IsProtocol = 0x1000,
            InitForFile = 0x2000,
        }

        internal enum AssocStr
        {
            Command = 1,
            Executable,
            FriendlyDocName,
            FriendlyAppName,
            NoOpen,
            ShellNewValue,
            DDECommand,
            DDEIfExec,
            DDEApplication,
            DDETopic,
            InfoTip,
            QuickTip,
            TileInfo,
            ContentType,
            DefaultIcon,
            ShellExtension,
            DropTarget,
            DelegateExecute,
            SupportedUriProtocols,
            Max,
        }
    }
"@
Add-Type -TypeDefinition $Signature
[Win32Api]::AssocQueryString(".docx")
like image 43
Dean Wookey Avatar answered Nov 09 '22 23:11

Dean Wookey