读取字符串实习池的内容

我想枚举字符串实习池中字符串

也就是说,我想得到string的所有实例s列表,这样:

 string.IsInterned(s) != null 

有谁知道这是否可能?

感谢@HansPassant的建议,我设法获得了程序集中的字符串文字列表。 这与我原本想要的非常接近。

您需要使用读取汇编元数据,并枚举用户字符串。 这可以通过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 } 

要获取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 { } 

这是怎么回事:

 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; 

其中location是程序集文件的路径。

之后,调用EnumUserStrings()GetUserString()是直截了当的。

这是一篇更详细的博客文章 ,以及GitHub上的一个演示项目 。

它指向的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 } 

如果您设法找到m_StringToEntryHashTable的本机地址,则可以枚举存在的字符串。