views:

271

answers:

6

Is it possible to read the GUID from the Assembly without actually loading it in the current App Domain.

Normally Assembly.Load loads the DLL into the app domain. I just want to read the value.

The description of the GUID is

'The following GUID is for the ID of the typelib 
' if this project is exposed to COM
<Assembly: Guid("DEDDE61CD-928E-4ACD-8C25-3B8577284819")> 

The main thing is I don't want to lock the file so that there are no errors 'Another process is accessing the file' error.

A: 

Try looking at this article: http://c-sharp-programming.blogspot.com/2008/08/how-to-get-c-assembly-guid.html

icemanind
-1: **without actually loading it**
Lasse V. Karlsen
Why -1? The link I posted describes how to do exactly what he is asking?
icemanind
I know how to read the GUID. But I want to just read the value not load the whole DLL into the App domain.
ggonsalv
A: 

Every .NET assembly is a PE (Program Executable) file. Its internal format is documented. If has IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR directory inside, which point to IMAGE_COR20_HEADER structure, which has reference to MetaData Section, which has Streams and StreamHeaders fields. You should find in the StreamHeaders the position of the stream thith the name #GUID and read it from Streams the corresponding data block. If you open with respect of IL Disassembler ildasm.exe (Windows SDK tool) a .NET DLL and its headers (see menu View and Headers) you will see the structure of steams.

You can read more information in http://msdn.microsoft.com/en-us/magazine/cc301808.aspx and http://www.ntcore.com/files/dotnetformat.htm#MetaSection and http://www.visualcplusdotnet.com/visualcplusdotnet5a.html (from the author of "Explorer Suite" which can you download from http://ntcore.com/exsuite.php).

You can also consider the way of using IID_IMetaDataDispenser to read matadata information from the assembly. See http://www.remotesoft.com/salamander/obfuscator/MyApp/MyPrivateLib.cpp.txt or "Meta" example from http://www.wheaty.net/downloads.htm

Oleg
+1  A: 

Since locking is your problem, you could get what you want by using a different AppDomain with Shadow Copy enabled (which is the very same functionality that ASP.NET uses to keep files unlocked) when loading the files. This does not lock the original file.

Other than that, there is an overload of Assembly.Load() which takes a byte[], so that you could first load the data into memory and then load the assembly from memory. Haven't tried this though, so that I don't know it this alternative approach actually works.

Lucero
A: 

I suggest you to create a separate AppDomain (AppDomain.CreateDomain()) first, then load the Assembly file into a byte array, call AppDomain.Load() which accepts a byte array, retrieve the Guid and finally use AppDomain.Unload() to unload the created AppDomain.

This will keep your memory clean, the assembly code is separated from your main application code, and of course the Assembly file won't be locked. Of course you should use some sort of cache to avoid loading the same file multiple times. File operations and reflection calls are pretty expensive (in terms of execution time).

Zim
+1  A: 

If you load an assembly using Assembly.ReflectionOnlyLoad(byte[]) it will load it as shadow and won't lock the file.

var bytes = File.ReadAllBytes(path);
var assembly = Assembly.ReflectionOnlyLoad(bytes);

This is typically how tools like Reflector access assemblies without locking them.

hemp
A: 

@Zim, You said file operation and reflection calls are pretty expensive. But isn't creating an AppDomian also expensive?

soni