microsoft / dotnet

This repo is the official home of .NET on GitHub. It's a great starting point to find many .NET OSS projects from Microsoft and the community, including many that are part of the .NET Foundation.
https://devblogs.microsoft.com/dotnet/
MIT License
14.42k stars 2.21k forks source link

Can a System.Reflection.Assembly.Location be changed? #809

Open CatGirlsAreLife opened 6 years ago

CatGirlsAreLife commented 6 years ago

So I am loading dll’s from a zip file using this Extension class located here: https://github.com/Elskom/Els_kom_new/blob/master/Els_kom_Core/Classes/AssemblyExtensions.cs

However I am not sure if they way I am loading it if their locations are set properly. I would like it to be \<assembly (or pdb or both) file name>. And if not, if I could manually change it in my method.

With that then one can tell from where exactly the assembly was loaded from in debug mode from the presence of the “.zip” on the path that vs says the filewas loaded from.

Also if desired I made the class friendly to the .NET framework if it is ever wanted or added to the .NET framework/Core. I personally do not mind it being added to it either. Just I wish I could just call it in my code as a static member of System.Reflection.Assembly though. I guess maybe that will happen when c# 8 comes.

Edit: After reading it seems there is a LoadModule method. Would it work in the case of this on this method to set the actual location to the way I want above? My reasoning for loading dll’s and pdb’s (if enabled in the program ui or when debugging the program itself in vs) is so that the program directory is not cluttered with installed plugins (simply installing them and their debug symbols to a zip or a Plugins folder based upon the user’s personal preference seems like a good idea). And yes on the program I plan to add a sort of plugins form or something for downloading updated plugins / installing & uninstalling them similar to vs extensions where it would require restarting the program to take effect. But if the .NET framework had a way of downloading, updating, installing and updating ‘plugins’ itself to a folder or file (like a zip file or something) by just passing in a url to it that would be nice too and much help as well. Currently I am of thinking things like the following:

AlexGhiondea commented 6 years ago

Hi -- I am not sure what exactly you are asking for -- would you mind restating the question?

CatGirlsAreLife commented 6 years ago

Basically I want to be able to see things like this for example when running in VS2017:

"path\to\zip\file.zip\someassembly.dll" Symbols Loaded.

basically a way to actually show the path to the assembly and the symbols file on debuggers would be great with my current implementation of loading assemblies from a zip file.

AlexGhiondea commented 6 years ago

You should be able to get the location of the assembly (the dll) by using reflection. The location of the PDB is not really something that Reflection would do. The debugger engines have a lot of heuristic for loading the PDB that matches a given assembly.

Can you tell me more about why you are interested in seeing the pdb location?

CatGirlsAreLife commented 6 years ago

I was thinking more about the actual dll location. although it would be nice if one could pass in a string to the Load(byte[]) and Load(byte[], byte[]) to fallback on instead of string.Empty on System.Reflection.Assembly.Location. That way I do not have to try to hack a workarround for it. https://github.com/Elskom/ZipAssembly/

But does the current function it calls before it does:

if (location != null) // some code for directory stuff

return location;

in the property even support files within zips? If it does then I do not have to worry but I load the files and their symbols in the zips from byte arrays.

AlexGhiondea commented 6 years ago

Would you mind sharing some code as to what you are trying to do?

If you want to load an assembly from disk using a file path, you can use the Assembly.LoadFrom(string assemblyFile) method.

I don't think we have a way to directly load an assembly from a zip archive.

CatGirlsAreLife commented 6 years ago

Sure, basically I want a way to have my Zip Assembly loader class to somehow override the normal Location property return value in the Assembly instance it creates to instead of being string.Empty because I pass the bytes of the zip entry content to the Load method to instead return like \<zip file name passed to my static LoadFromZip method>\\<entry path of file to load from zip passed to my static LoadFromZip method>.

The code to that class is located here: https://github.com/Elskom/ZipAssembly/blob/master/ZipAssembly.cs and: https://github.com/Elskom/Els_kom_new/blob/master/Els_kom_Core/Classes/AssemblyExtensions.cs

However both have a lot of hacking, sadly the only way currently to get what I want is to reimplement much of System.Reflection itself which is not the best solution. What we need is some way to do the original work, check if someone registered some special things to do instead (if loaded from byte arrays) of the original behavior. Maybe like some sort of way to pass in the override string to return somehow whenever getting the location of an assembly instance loaded with my zip loader.

In one of them I derive from assembly but if I did so would it overwrite the normal behavior on Assemblies not loaded from a zip file?

Maybe it is possible that when loading from any of the Load(byte[][, , ]) functions that it sets some bool to true that then the implemented Location property checks if true then if it is invoke a user defined event (if defined) that passes a event args class or something that someone can set with the path string the event wants to return, then return that string from the Location property. That way the event is set per instance if it is needed to be defined and invoked. Then this code could work with a lot less hacks to the open parts of the .NET framework that cannot be compiled by anyone to test changes on their end. Oh how I wish I could test changes I make to the .NET framework to see if they would be practical to do/add there.

Sorry for the hard links, I cannot use the good backtick code block that I can specify language for syntax highlighting on my iPhone 5s. Also the first link I plan to have it in a class library of itself relating to it all, and the second link I would use that class library as a dependency and then remove that file there. However this change needs to happen I think somehow.

AlexGhiondea commented 6 years ago

Thanks for the additional information. Do you have a hard requirement to return an object that is of type Assembly? Or can you return your type that encapsulates the assembly?

Do you have a sample of how your code is going to be used?

CatGirlsAreLife commented 6 years ago

I would like to return Assembly yes, and the code is used specifically for loading plugins. I tested the loader class I got so far in my code and it loads the assembly fine from a zip file.

The plugin loader is located here: https://github.com/Elskom/Els_kom_new/blob/master/Els_kom_Core/Classes/GenericPluginLoader.cs

AlexGhiondea commented 6 years ago

Thanks -- so the issue you are seeing now is that you don't have a way to overwrite the location of the assembly object once you load it.

I think the current behavior is by-design. You can file an issue in the CoreFx repo to change this behavior, but due to compatibility reasons that might not be something we can do.

katherinebai commented 2 years ago

How could I set Assembly Location when load assembly from bytes array? Because I need find some resources(icon, etc). And I don't want to save Assembly to file firstly and then to load it.