C#获取文件类型的默认应用程序

时间:2018-11-16 06:52:32

标签: c# file interop

我正在使用此代码来获取“ .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 :(得分:1)

AssocQueryString 是WinAPI函数。这是一种系统级通用功能,可以在不同类型的应用程序中使用。使用应用程序可能对性能和/或内存要求非常严格。这就是WinAPI函数从不进行内存分配的原因(因为内存分配可能是一项相对昂贵的任务性能),它们期望调用者将所有必需的内存提供给它们。

在许多情况下(例如使用此 AssocQueryString 功能),在执行函数之前,您可能不知道所需的内存量。在这里,API开发人员将两个功能“合并”为一个:如果使用空值而不是输出字符串调用 AssocQueryString ,它将计算出所需的字符串长度,否则将使用您提供的字符串,期望您已经为该字符串分配了足够的内存。

您不必担心两次调用该函数。实际上,您在调用两个略有不同的函数:一个是计算所需的字符串长度,另一个是实际完成工作(即在注册表中搜索文件关联)。