Hello William,
I'm not sure if this is availabe via managed code.
The version of the CLR used when the assembly was built is recorded into
assembly during the compiling.
Thus you need to analyze PE header to get this info. This version string
is located in a 16 bytes after the start of the metadata section
See samples below describing how to get this info
// The CLR metadata header is currently 16 bytes.
#define CLR_MD_HEADER_SIZE 16
DWORD ConvertVirtualAddressToOffset(IMAGE_NT_HEADERS *pNtHeader, DWORD virtualAddress)
{
// find the right section
ULONG i;
PIMAGE_SECTION_HEADER pNtSection;
pNtSection = IMAGE_FIRST_SECTION( pNtHeader );
for (i=0; i<pNtHeader->FileHeader.NumberOfSections; i++)
{
if (virtualAddress >= pNtSection->VirtualAddress &&
virtualAddress < pNtSection->VirtualAddress + pNtSection->SizeOfRawData)
break;
++pNtSection;
}
// compute offset from va
assert(pNtSection);
return ((virtualAddress - pNtSection->VirtualAddress) + pNtSection->PointerToRawData);
}
int _tmain(int argc, _TCHAR* argv[])
{
if (argc < 2)
{
printf("Usage: ClrVersion <Exe or Dll name>\n");
return 0;
}
// error checking to determine if the file is in fact a PE is omitted.....
// open the file
HANDLE hFile = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
assert (hFile != INVALID_HANDLE_VALUE);
// Create a file mapping object
HANDLE hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0,
NULL);
assert (hFile != INVALID_HANDLE_VALUE);
// Map the file
PBYTE pbFile = NULL;
pbFile = (PBYTE) MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
assert(pbFile);
// Get the nt header
IMAGE_DOS_HEADER *pDosHeader = (IMAGE_DOS_HEADER*)pbFile;
IMAGE_NT_HEADERS *pNtHeader = (IMAGE_NT_HEADERS*)(pbFile + pDosHeader->e_lfanew);
// Skip to the clr header. If the directory entry for clr isn't filled in
we know
// this isn't a managed PE
DWORD dwClrHeaderVA = pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;
if (dwClrHeaderVA == 0)
{
printf("%s is not a managed executable file\n", argv[1]);
return 0;
}
DWORD dwClrHeaderOffset = ConvertVirtualAddressToOffset(pNtHeader, dwClrHeaderVA);
IMAGE_COR20_HEADER* pCorHeader = (IMAGE_COR20_HEADER*) (pbFile + dwClrHeaderOffset);
// The version string is stored near the beginning of the metadata section.
Skip to
// the metadata and find the string.
DWORD dwClrMDVA = pCorHeader->MetaData.VirtualAddress;
DWORD dwClrMDOffset = ConvertVirtualAddressToOffset(pNtHeader, dwClrMDVA);
LPBYTE pMetaData = (pbFile + dwClrMDOffset);
// the string starts 16 bytes from the beginning of the metadata section
LPCSTR pVersion = (LPCSTR) (pMetaData + CLR_MD_HEADER_SIZE);
printf("%s was built with %s of the CLR\n", argv[1], pVersion);
// clean up
UnmapViewOfFile(pbFile);
CloseHandle(hFileMapping);
CloseHandle(hFile);
return 0;
}
WL> I forgot but this is about "windows application"
WL>
WL> "William Leme" wrote:
WL>---
WBR,
Michael Nemtsev :: blog:
http://spaces.msn.com/laflour
"At times one remains faithful to a cause only because its opponents do not
cease to be insipid." (c) Friedrich Nietzsche