我正在使用此代码来获取“ .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();
}
答案 0 :(得分:1)
AssocQueryString 是WinAPI函数。这是一种系统级通用功能,可以在不同类型的应用程序中使用。使用应用程序可能对性能和/或内存要求非常严格。这就是WinAPI函数从不进行内存分配的原因(因为内存分配可能是一项相对昂贵的任务性能),它们期望调用者将所有必需的内存提供给它们。
在许多情况下(例如使用此 AssocQueryString 功能),在执行函数之前,您可能不知道所需的内存量。在这里,API开发人员将两个功能“合并”为一个:如果使用空值而不是输出字符串调用 AssocQueryString ,它将计算出所需的字符串长度,否则将使用您提供的字符串,期望您已经为该字符串分配了足够的内存。
您不必担心两次调用该函数。实际上,您在调用两个略有不同的函数:一个是计算所需的字符串长度,另一个是实际完成工作(即在注册表中搜索文件关联)。