C # получить приложение по умолчанию для типа файла - PullRequest
0 голосов
/ 16 ноября 2018

Я использую этот код, чтобы получить приложение по умолчанию для типов файлов, таких как ".txt". Он работает совершенно нормально, но почему я должен вызывать один и тот же метод два раза? Единственное, что я узнал, это то, что lenth устанавливается после первого звонка. Но действительно ли мне нужно выполнять функцию дважды, потому что сначала мне нужна длина?

Если я выполню его только один раз, он вылетит.

КОД

using System.Runtime.InteropServices;
[DllImport("Shlwapi.dll", CharSet = CharSet.Unicode)]
public static extern uint AssocQueryString(
    AssocF flags, 
    AssocStr str,  
    string pszAssoc, 
    string pszExtra, 
    [Out] StringBuilder pszOut, 
    ref uint pcchOut
); 
[Flags]
public enum AssocF
{
    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_Fixed_ProgId = 0x800,
    Is_Protocol = 0x1000,
    Init_For_File = 0x2000
}
public enum AssocStr
{
    Command = 1,
    Executable,
    FriendlyDocName,
    FriendlyAppName,
    NoOpen,
    ShellNewValue,
    DDECommand,
    DDEIfExec,
    DDEApplication,
    DDETopic,
    InfoTip,
    QuickTip,
    TileInfo,
    ContentType,
    DefaultIcon,
    ShellExtension,
    DropTarget,
    DelegateExecute,
    Supported_Uri_Protocols,
    ProgID,
    AppID,
    AppPublisher,
    AppIconReference,
    Max
}

ОБРАЗЕЦ ИСПОЛЬЗОВАНИЯ:

static string AssocQueryString(AssocStr association, string extension)
    {
        const int S_OK = 0;
        const int S_FALSE = 1;

        uint length = 0;
        uint ret = AssocQueryString(AssocF.None, association, extension, null, null, ref length);
        if (ret != S_FALSE)
        {
            throw new InvalidOperationException("Could not determine associated string");
        }

        var sb = new StringBuilder((int)length); // (length-1) will probably work too as the marshaller adds null termination
        ret = AssocQueryString(AssocF.None, association, extension, null, sb, ref length);
        if (ret != S_OK)
        {
            throw new InvalidOperationException("Could not determine associated string"); 
        }

        return sb.ToString();
    }

1 Ответ

0 голосов
/ 16 ноября 2018

AssocQueryString - это функция WinAPI.Это своего рода функция общего назначения системного уровня, которая может использоваться в различных приложениях.Использование приложений может иметь ОЧЕНЬ жесткие требования к производительности и / или памяти.Вот почему функции WinAPI никогда не выполняют выделение памяти самим (поскольку выделение памяти может быть относительно дорогостоящим в плане производительности задачи), они ожидают, что вызывающая сторона предоставит им всю необходимую память.

Во многих случаях (например, с помощью этой AssocQueryString ) человек не может знать требуемый объем памяти перед выполнением функции.Здесь разработчики API «слили» две функции в одну: если вы вызовете AssocQueryString со значением NULL вместо выходной строки, он вычислит необходимую вам длину строки, в противном случае он будет использовать указанную вами строку, ожидая, что выВы уже выделили достаточно памяти для этой строки.

Вам не нужно беспокоиться о вызове функции дважды.На самом деле, вы вызываете две слегка отличающиеся функции: одна для вычисления необходимой длины строки, а другая для фактического выполнения работы (т. Е. Поиска в реестре файловой ассоциации).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...