Read the contents of the row pool

I would like to list the rows that are in the old pool . .

That is, I want to get a list of all instances of s of string such that:

 string.IsInterned(s) != null 

Does anyone know if this is possible?

+6
source share
2 answers

Thanks to the advice of @HansPassant, I was able to get a list of string literals in the assembly. Which is very close to what I originally wanted.

You need to use assembly read metadata and list custom strings. This can be done using these three IMetaDataImport methods:

 [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 an instance of IMetaDataImport , you need to get 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's how to do it:

 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 build file.

After that, the call to EnumUserStrings() and GetUserString() is disconnected.

Here 's a blog post with more details and a demo project on GitHub .

+2
source

SSCLI function indicating that it is

 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 can find your own m_StringToEntryHashTable address, you can list the existing lines.

+1
source

All Articles