Replacing a base assembly with source code in .NET - c#

Suppose you have an assembly B that references A and you have the source code for the assembly A only. Is it possible to build from source code the assembly A and debug it?
Currently we get this error:
Could not load file or assembly 'name' or one of its dependencies. The
located assembly's manifest definition does not match the assembly
reference.
Is there any way to bypass it?

This will depend on if the original assembly A that is referenced is strongly named. This is a feature where assemblies are signed. Keys for all compile time references are stored in the built assembly, B in your case. When loading assemblies the loader may then verify the signatures of all references to ensure the correct assembly is loaded.
So if strong naming is used it is not easy to replace the assembly A with a newer version without recompiling B. There is however a strong name validation bypass feature for full trust application domains.
If you manage to bypass or disable the strong naming you should simply be able to replace the file in the directory with the new version and attach visual studio.

Related

How does CLR load a file from an assembly?

Below is a multifile assembly consisting of two managed modules, one with a manifest:
so RUT.netmodule(RUT stands for rare used types) is a file(.netmodule) that's part of the assembly.
Let's say my client application references a type from RUT.netmodule and MultiFileLibrary.dll is a strong name assembly and it is installed in GAC.
Because RUT.netmodule doesn't physically reside in MultiFileLibrary.dll, so GAC won't have RUT.netmodule.
so my question is, maybe CLR is configured to check application's base directory to look for RUT.netmodule after it knows that the referenced type is in a different module file. But it also means that RUT.netmodule have to always in application's base directory, which sounds strange to me as if I have mutiple applications then I need to have multiple RUT.netmodule in their base directory. Is a way to "install" RUT.netmodule in GAC or when MultiFileLibrary.dll is installed in GAC, any .netmodule files are also copied into GAC?
I have never working with multi-file assemblies but as far as I can tell you should be able to sign the .netmodule by using the assembly linker tool (al.exe).
The documentation contains a small quote which might be relevant:
How to: Sign an assembly with a strong name
...
By using the Assembly Linker (Al.exe) to link a .NET Framework code module (a .netmodule file) with a key file.
My guess is that even when you place the assembly in GAC it will still reference the .netmodule and it should work if the .netmodule is signed.
Hope this information helps you.

.net - Added a strong named assembly, but it is looking for unsigned assembly

So, I have two projects... One is a big class library, and the other is a big simulator project.
Originally during testing the assemblies were not strong-named, but now that I need COM visibility, I need to strong name them (I need this quick, and it is easier to make them COM visible rather than deal with the CLI).
I generated a .snk and added it to the properties of each of the projects, the class library compiles just fine and outputs the .dll just fine. I added this .dll as a reference in the simulator project, but now the simulator project is giving me the following error:
The type "DynamicsControl" is defined in an assembly that is not
referenced. You must add a reference to assembly "DynamicsControl,
Version=0.4.3.0, Culture=neutral, PublicKeyToken=null"
The type DynamicsControl does exist in the class library (I verified), but it is claiming I am not loading the correct assembly. I believe it is the PublicKeyToken=null that is causing the issue (as my assembly would have a public key).
When I do sn -Tp DynamicsControl.dll (the one in the location I am referencing), it outputs the private and public key, so I know it has a proper signature.
What step am I missing? Do I have to add the assembly to the GAC? Do I manually have to add the public key?
Yes you need to specify the publicKeyToken for a strong named assembly otherwise it will look for unsigned version of the assembly. You can find out the public key token either by adding the assembly to GAC (and you will see it there) or by using the steps mentioned in the this link
If you want to read more about strong name and dll hell you can go to this URL .
Strong name prevents from dll hell which means you can have multiple versions of same assembly.
To your other question you don't have to add the assembly to GAC but CLR will look for the assembly first in GAC and then other places. Also, you don't have to add the key manually. If you remove the reference and add it back using the signed assembly it should automatically take the key.

Reflection and strong named assemblies

I have created a test project whose output will be strong named assembly. I have specified the SNK file name in the 'project -> properties - > Signing' section so that assembly will be strong named.
I added reference of the assembly which is NOT signed or strong named. I was expecting that my project will not at all build since it's referencing unsigned assembly. However, it built and i could install the assembly in GAC too! Why is it so? (I'm using .NEt 4.0 and it's gacutil.exe)
Note: I have ensured that the assembly which is being referenced is NOT strong named.
Can i programatically load the 'unsigned' (i.e. non-strong named) assembly in my program whose output is going to be strong named assembly? If yes, why is it allowed to do so when on the other hand, .NET don't allow to add reference to unsigned assemblies?
If I have multiple versions of the same assembly in GAC. In my configuration file, If I specify just the name of the assembly, which version will be loaded from GAC? Will it be latest version everytime? Which API will be useful? I found many methods marked 'deprecated' in Assembly class.
You can reference the unsigned assembly in VS.Net from a signed assembly. But if you call anything from the signed to the unsigned, the build will fail.
There is no problem in signed assembly referencing an unsigned assembly. It can be done and signed assembly can be GACed.
Yes, you can load.
How can you specify assembly by just name ? There is only one API LoadWithPartialName and thats deprecated for many reasons. You need version, culture and public key token to uniquely identify assembly.

Strongly signed assemblies

I am not a .NET developer, so there might be some basic things I don't know.
I have some experience coding in C#, but now I have a question. One of my projects (A) references another ptoject (B), with "local copy" set. When B.dll is in the same location as A.exe everything works. But when B.dll is put in a common directory from PATH it doesn't work.
One of my coworkers said he thought I should make B strongly signed. Is he correct? Is that why one would strongly sign an assembly?
I read a bit about in in the internet but all I saw was about security... If so, how does one sign an assembly and what consequences does it have? Please note that I am using VS2003 .Net 1.1.
Edit: Thank you all very much for your answers, however all the links you provided refer to later versions of VS and .NET which have some sort of Signing tab in project properties. Does anybody know (or give a link )how to strongly name the assembly in VS2003 .Net1.1?
Your problem is not related to assembly signing in the first place. .NET does not use the PATH environment variable to load assemblies. The process is actually a bit more complex and you best read all details in MSDN (also see steps 1 to 4):
How the Runtime Locates Assemblies
In your case it might be the best to install the shared assembly to the GAC. Installing to the GAC requires that your assembly has a strong name, so this is probably what your co-worker referred to.
Update:
As you asked specifically about strong-naming a .NET 1.1 assembly I'd suggest checking out the following question:
How to give a .NET 1.1 dll a strong name in VS2003
I think that what your co-worker might be referring to is "Strong Naming" an Assembly.
Strong Naming is what enables you to deploy your assembly to the GAC.
Once it is in the GAC, then any application using that assembly can always locate it. Path's are irrelevant and that is the preferred way to have shared assemblies deployed.
To strong name an assembly, you can use the sn.exe tool that comes with Visual Studio to generate a strong name and then sign the assembly using the keyfile that is generated via sn.exe.
EDIT : Example of how to use SN.exe to strong name an assembly is here
Also, I think you should understand how the runtime loads assemblies. From MSDN
The runtime uses the following steps to resolve an assembly reference:
Determines the correct assembly version by examining applicable
configuration files, including the application configuration file,
publisher policy file, and machine configuration file.
If the configuration file is located on a remote machine, the
runtime must locate and download the application configuration file
first.
Checks whether the assembly name has been bound to before and, if so,
uses the previously loaded assembly.
Checks the global assembly cache. If the assembly is found there, the
runtime uses this assembly.
Probes for the assembly using the following steps: If configuration
and publisher policy do not affect the original reference and if the
bind request was created using the Assembly.LoadFrom method, the
runtime checks for location hints.
If a codebase is found in the configuration files, the runtime checks
only this location. If this probe fails, the runtime determines that
the binding request failed and no other probing occurs.
Probes for the assembly using the heuristics described in the probing
section. If the assembly is not found after probing, the runtime
requests the Windows Installer to provide the assembly. This acts as
an install-on-demand feature.
Note: There is no version checking for assemblies without strong
names, nor does the runtime check in the global assembly cache for
assemblies without strong names.
The right way to do this is by deploying your .dll in the GAC. http://support.microsoft.com/kb/815808
what is the reason you want to put the B.dll in a common directory? is it because it can be used by a another program? if so adding it to the GAC is the best option. See this one
As 0xA3 already mentioned you should read the article at MSDN. But what is not so good explained in the article is the usage of the AssemblyResolve event. It will be thrown if the Framework didn't find the assembly at any place, givin you a chance to start a search on yourself (maybe in your common folder) and return the needed assembly.
An example on how to use this, can be found in my question here.

How to add assembly manifest to a C# .NET class library project in Visual Studio 2008?

I'm having a similar problem to what Paul had a year ago (see How to add manifest to a .NET DLL?). That is, I have a C# class library project in Visual Studio 2008, which outputs a dll. The dll references some private assemblies, so I want to add an assembly manifest to the dll that specifies those other referenced assemblies.
I know how to do this for an executable, it's just appName.exe.manifest, and when the file is included in the project, you can then just select it as the manifest in the project properties.
According to the answer that Ruben gave Paul (in the above Stack Overflow thread), a manifest only applies to exes. However, the Microsoft documentation on manifests seems to suggest otherwise (correct me if I'm wrong), MSDN Assembly Manifests:
An assembly manifest is an XML file
that describes a side-by-side
assembly. Assembly manifests describe
the names and versions of side-by-side
assemblies, files, and resources of
the assembly, as well as the
dependence of the assembly on other
side-by-side assemblies. Correct
installation, activation, and
execution of side-by-side assemblies
requires that the assembly manifest
always accompany an assembly on the
system.
Because of the way side-by-side
searches for private assemblies, the
following naming restrictions apply
when packaging a DLL as a private
assembly. A recommended way of doing
this is to put the assembly manifest
in the DLL as a resource. In this
case, the resource ID must equal 1 and
the name of the private assembly may
be the same as the name of the DLL.
For example, if the name of the DLL is
Microsoft.Windows.mysample.dll, the
value of the name attribute used in
the assemblyIdentity element of the
manifest may also be
Microsoft.Windows.mysample.
An alternate way is to put the
assembly manifest in a separate file.
In this case, the name of the assembly
and its manifest must be different
than the name of the DLL. For example,
Microsoft.Windows.mysampleAsm,
Microsoft.Windows.mysampleAsm.manifest,
and Microsoft.Windows.Mysample.dll
So I created an assembly manifest assemblyName.manifest as a separate file, and included it in the class library project. But when I go to the properties for the project, I get the same result that Paul did, the option to use your own manifest is disabled.
Am I doing something wrong? How do I add my manifest to the assembly?
What you quoted is quite inappropriate for .NET assemblies. The Windows side-by-side cache is for unmanaged DLLs, the exact equivalent in .NET is the GAC. Furthermore, the compiler already embeds references to the dependent assemblies in the assembly manifest. You can see it if you run Ildasm.exe on your assembly. Double-click the manifest, you'll see the .assembly directives listed.
Fwiw, embedding your own Windows manifest in a class library is not a problem. Just use Project + Add New Item and select the Application Manifest File template item. The auto-generated content is completely wrong for a DLL of course but it does get embedded in the DLL. You can see that by using File + Open + File and selecting your assembly. You'll see the RT_MANIFEST with resource ID 2. Just to reiterate: don't do this for a managed DLL unless you want to enter reg-free COM directives.

Categories

Resources