3

特定の拡張子のファイルを開くために使用される実行可能ファイルを見つけようとしているので、拡張子にアイコンがない場合はその実行可能ファイルのアイコンを表示できます。

ファイル タイプの HKEY_CLASSES_ROOT レジストリ キーに open 動詞があることは認識していますが、その値が常に正しいとは限らないことがわかりました。

たとえば、私は現在 OS X 上の Parallels で Windows を実行しています。PDF ファイルのデフォルトの関連付けは Safari でした。エクスプローラーを使用して、デフォルトの関連付けを Adob​​e Reader に変更しました。レジストリの開く動詞は Safari のままですが、PDF ファイルをダブルクリックすると、Adobe Reader で開きます。32 ビット レジストリと 64 ビット レジストリの値は同じです。

.NET または winapi を使用して、ファイルの種類の関連付けを取得するより良い方法はありますか?

4

3 に答える 3

3

あなたの最善の策は、おそらくPInvoke を介してandAssoc*などの関数のグループを使用することです。ただし、.NET フレームワークに付属する多くのクラスの 1 つが、その多くの化身で既にこれをラップしているかどうかはわかりません。ただし、Shell API には、この情報を取得するオプションがあります。AssocQueryKey()AssocQueryString()

また、上記の関数はインターフェイスのラッパーであると述べている注釈セクションにも注意してくださいIQueryAssociations。これにより、.NET 内から必要なものへの別のより直接的なルートがある可能性がさらに高くなります。

古いスタイルの関数はこれでした: FindExecutable(). ただし、使用しないでください。と同じ欠陥のあるエラー コード マジックを使用しShellExecute()ます。

Windowsの回答も参照してください: 拡張機能に関連付けられたアプリケーションの一覧表示と起動

于 2012-11-19T20:15:01.117 に答える
2

いくつかの一般的なエラーを防ぐためのチェックを含む私のコード...それが役立つことを願っています:-)

using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;

namespace HQ.Util.Unmanaged
{
    /// <summary>
    /// Usage: string executablePath = FileAssociation.GetExecFileAssociatedToExtension(pathExtension, "open");
    /// Usage: string command FileAssociation.GetExecCommandAssociatedToExtension(pathExtension, "open");
    /// </summary>
    public static class FileAssociation
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="ext"></param>
        /// <param name="verb"></param>
        /// <returns>Return null if not found</returns>
        public static string GetExecCommandAssociatedToExtension(string ext, string verb = null)
        {
            if (ext[0] != '.')
            {
                ext = "." + ext;
            }

            string  executablePath = FileExtentionInfo(AssocStr.Command, ext, verb);

            // Ensure to not return the default OpenWith.exe associated executable in Windows 8 or higher
            if (!string.IsNullOrEmpty(executablePath) && File.Exists(executablePath) &&
                !executablePath.ToLower().EndsWith(".dll"))
            {
                if (executablePath.ToLower().EndsWith("openwith.exe"))
                {
                    return null; // 'OpenWith.exe' is th windows 8 or higher default for unknown extensions. I don't want to have it as associted file
                }
                return executablePath;
            }
            return executablePath;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="ext"></param>
        /// <param name="verb"></param>
        /// <returns>Return null if not found</returns>
        public static string GetExecFileAssociatedToExtension(string ext, string verb = null)
        {
            if (ext[0] != '.')
            {
                ext = "." + ext;
            }

            string executablePath = FileExtentionInfo(AssocStr.Executable, ext, verb); // Will only work for 'open' verb
            if (string.IsNullOrEmpty(executablePath))
            {
                executablePath = FileExtentionInfo(AssocStr.Command, ext, verb); // required to find command of any other verb than 'open'

                // Extract only the path
                if (!string.IsNullOrEmpty(executablePath) && executablePath.Length > 1) 
                {
                    if (executablePath[0] == '"')
                    {
                        executablePath = executablePath.Split('\"')[1];
                    }
                    else if (executablePath[0] == '\'')
                    {
                        executablePath = executablePath.Split('\'')[1];
                    }
                }
            }

            // Ensure to not return the default OpenWith.exe associated executable in Windows 8 or higher
            if (!string.IsNullOrEmpty(executablePath) && File.Exists(executablePath) &&
                !executablePath.ToLower().EndsWith(".dll"))
            {
                if (executablePath.ToLower().EndsWith("openwith.exe"))
                {
                    return null; // 'OpenWith.exe' is th windows 8 or higher default for unknown extensions. I don't want to have it as associted file
                }
                return executablePath;
            }
            return executablePath;
        }

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

        private static string FileExtentionInfo(AssocStr assocStr, string doctype, string verb)
        {
            uint pcchOut = 0;
            AssocQueryString(AssocF.Verify, assocStr, doctype, verb, null, ref pcchOut);

            Debug.Assert(pcchOut != 0);
            if (pcchOut == 0)
            {
                return "";
            }

            StringBuilder pszOut = new StringBuilder((int)pcchOut);
            AssocQueryString(AssocF.Verify, assocStr, doctype, verb, pszOut, ref pcchOut);
            return pszOut.ToString();
        }

        [Flags]
        public enum AssocF
        {
            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
        }

        public enum AssocStr
        {
            Command = 1,
            Executable,
            FriendlyDocName,
            FriendlyAppName,
            NoOpen,
            ShellNewValue,
            DDECommand,
            DDEIfExec,
            DDEApplication,
            DDETopic
        }



    }
}
于 2014-04-29T18:23:41.553 に答える
-1

HKEY_USERS\{User}\Software\Classes も確認する必要があります。ユーザーは、独自のデフォルト アプリケーションをオーバーライドできます。

于 2012-11-19T20:08:49.487 に答える