[英]Read the content of the string intern pool
I would like to enumerate the strings that are in the string intern pool . 我想枚举字符串实习池中的字符串 。
That is to say, I want to get the list of all the instances s
of string
such that: 也就是说,我想得到string
的所有实例s
列表,这样:
string.IsInterned(s) != null
Does anyone know if it's possible? 有谁知道这是否可能?
Thanks to the advice of @HansPassant, I managed to get the list of string literals in an assembly. 感谢@HansPassant的建议,我设法获得了一个程序集中的字符串文字列表。 Which is extremely close to what I originally wanted. 这与我原本想要的非常接近。
You need to use read assembly meta-data, and enumerate user-strings. 您需要使用读取汇编元数据,并枚举用户字符串。 This can be done with these three methods of IMetaDataImport
: 这可以通过IMetaDataImport
这三种方法来完成:
[ComImport, Guid("7DAC8207-D3AE-4C75-9B67-92801A497D44")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IMetaDataImport
{
void CloseEnum(IntPtr hEnum);
uint GetUserString(uint stk, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] char[] szString, uint cchString, out uint pchString);
uint EnumUserStrings(ref IntPtr phEnum, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]uint[] rStrings, uint cmax, out uint pcStrings);
// interface also contains 62 irrelevant methods
}
To get the instance of IMetaDataImport
, you need to get a IMetaDataDispenser
: 要获取IMetaDataImport
的实例,您需要获取IMetaDataDispenser
:
[ComImport, Guid("809C652E-7396-11D2-9771-00A0C9B4D50C")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[CoClass(typeof(CorMetaDataDispenser))]
interface IMetaDataDispenser
{
uint OpenScope([MarshalAs(UnmanagedType.LPWStr)]string szScope, uint dwOpenFlags, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppIUnk);
// interface also contains 2 irrelevant methods
}
[ComImport, Guid("E5CB7A31-7512-11D2-89CE-0080C792E5D8")]
class CorMetaDataDispenser
{
}
Here is how it goes: 这是怎么回事:
var dispenser = new IMetaDataDispenser();
var metaDataImportGuid = new Guid("7DAC8207-D3AE-4C75-9B67-92801A497D44");
object scope;
var hr = dispenser.OpenScope(location, 0, ref metaDataImportGuid, out scope);
metaDataImport = (IMetaDataImport)scope;
where location
is the path to the assembly file. 其中location
是程序集文件的路径。
After that, calling EnumUserStrings()
and GetUserString()
is straighforward. 之后,调用EnumUserStrings()
和GetUserString()
是直截了当的。
Here is a blog post with more detail , and a demo project on GitHub . 这是一篇更详细的博客文章 ,以及GitHub上的一个演示项目 。
The SSCLI function that its pointing to is 它指向的SSCLI函数是
STRINGREF*AppDomainStringLiteralMap::GetStringLiteral(EEStringData *pStringData)
{
...
DWORD dwHash = m_StringToEntryHashTable->GetHash(pStringData);
if (m_StringToEntryHashTable->GetValue(pStringData, &Data, dwHash))
{
STRINGREF *pStrObj = NULL;
pStrObj = ((StringLiteralEntry*)Data)->GetStringObject();
_ASSERTE(!bAddIfNotFound || pStrObj);
return pStrObj;
}
else { ... }
return NULL; //Here, if this returns, the string is not interned
}
If you manage to find the native address of m_StringToEntryHashTable, you can enumerate the strings that exist. 如果您设法找到m_StringToEntryHashTable的本机地址,则可以枚举存在的字符串。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.