Shared Assembly in GAC and its dependencies assemblies

  • Thread starter Thread starter MA
  • Start date Start date
M

MA

Hi,

We have added a shared assembly in GAC so that our multiple solutions
can use use it. We use the publisher policy to controls the different
versions of the assembly.

This shared assembly also has dependencies (some are .NET assembly
with strong name and some non .NET without strong name). How we will
manage the dependent assemblies? Does the dependent assemblies will
need to be added to the GAC?

Obviously we will not able to add the weak name assembly to the GAC.
How can we manage one copy of the weak named assembly so that we can
update in future?

We will prefer not make local references of the dependent assemblies
(i.e. assemblies will need to be exists in solution installation
folder) so that we can update the dependent assemblies if required
without updating each solution.


Example:
Assembly1: depend on Assembly2 (strong named) & Assembly3 (weak
named).
Assembly1 added to the GAC. Do we need to add the Assembly2 to the GAC
as well? The Assembly3 is not strong named, how we will manage the
Assembly3? Does each solution will need the local copy of the
Assembly3 or can we add to the "c:\program files\shared" and manage it
centrally?


Hope this make sense and thanks in advance for your suggestions.

Regards,
MA
 
Hi,

I have came across the article below which recommend to place the un-
managed assembly to the GAC by creating a managed wrapper assembly.
This approach answer the issue above where we will need to put all the
dependent assemblies to GAC (managed+un-managed).

http://blogs.msdn.com/yizhang/archive/2007/06/17/how-to-deploy-unmanaged-dll-into-gac.aspx

Let's say you have a managed wrapper assembly Managed.dll that calls
unmanaged code Unmanaged.dll using P/Invoke. If you want to register
Managed.dll to GAC, you'll need to deploy Unmanaged.dll into GAC as
well, otherwise it would require extra work to be done so that
Managed.dll can find Unmanaged.dll. To deploy both Manage.dll &
Unmanaged.dll into GAC, you can create a multi-file assembly
consisting both Managed.dll & Unmanaged.dll. In order to create such a
assembly, you can:

1. Use /LinkResource option in C# compiler (CSC.EXE) if you are using
C#
2. Use /AssemblyLinkResource option in C++ compiler (CL.EXE) if you
are using managed C++
3. Use /Link option in Assembly Linker (AL.EXE)

Any Pros & Cons about this approach?

Regards,
MA
 
MA said:
Let's say you have a managed wrapper assembly Managed.dll that calls
unmanaged code Unmanaged.dll using P/Invoke. If you want to register
Managed.dll to GAC, you'll need to deploy Unmanaged.dll into GAC as
well, otherwise it would require extra work to be done so that
Managed.dll can find Unmanaged.dll. To deploy both Manage.dll &
Unmanaged.dll into GAC, you can create a multi-file assembly
consisting both Managed.dll & Unmanaged.dll. In order to create such a
assembly, you can:

1. Use /LinkResource option in C# compiler (CSC.EXE) if you are using
C#
2. Use /AssemblyLinkResource option in C++ compiler (CL.EXE) if you
are using managed C++
3. Use /Link option in Assembly Linker (AL.EXE)

Any Pros & Cons about this approach?[/QUOTE]

No cons that I know of, if you don't mind the extra work.

By the way, the same trick can be used to get the .pdb for your assembly to
be deployed to GAC automatically - just add it as a LinkResource.
 
Thanks for your response.

Btw, I have tried to create the wrapper assembly using the C#
compiler but without any success. The C# compiler (CSC) require a
target file (I am not sure what is the target file to enter). I want
to add the unmanaged.dll (written in Delphi) to the managed dll
(written in C#). Any suggestions?

Regards,
MA
 
Just another thought....

Can we have the local copy of the dependent assembly to the solution
installation folder? For example,

We have a AssemblyA (written in C#) which we added to the GAC.
AssemblyA has the references of AssemblyB (written in Delphi) and
other interop assemblies (un-managed).

Can we have the local copy of these un-managed assmblies to the
solution installation folder? How the assembly loader will work where
the AssemblyA in GAC but the dependencies are in solution installation
folder.

Thanks for your advice.

Regards,
MA
 
MA said:
Btw, I have tried to create the wrapper assembly using the C#
compiler but without any success. The C# compiler (CSC) require a
target file (I am not sure what is the target file to enter). I want
to add the unmanaged.dll (written in Delphi) to the managed dll
(written in C#). Any suggestions?

Why not just use /linkresource when you compile your managed .dll?
 
MA said:
Just another thought....

Can we have the local copy of the dependent assembly to the solution
installation folder? For example,

We have a AssemblyA (written in C#) which we added to the GAC.
AssemblyA has the references of AssemblyB (written in Delphi) and
other interop assemblies (un-managed).

Can we have the local copy of these un-managed assmblies to the
solution installation folder? How the assembly loader will work where
the AssemblyA in GAC but the dependencies are in solution installation
folder.

I'm afraid it won't work that way.
 
Thanks Pavel for your suggestions.

I have performed the steps below but seems the unmanaged.dll still
required by the solution. Any idea?

1. Compile the library.
Example: CSC /platform:x86 /errorreport:prompt /out:"D:\test\bin
\Debug\MySystem.dll" /reference:"C:\WINDOWS\Microsoft.NET\Framework
\v2.0.50727\System.Windows.Forms.dll" /LinkResource:"D:\test
\unmanaged.dll" /target:library "D:\test\CommonTypes.cs" "D:\test
\Condition.cs" "D:\test\ConditionStatus.cs" /keyfile:"D:\test\Key.snk"

2. Add the "MySystem.dll" to GAC

3. In my Tester solution, add the shared GAC - "MySystem.dll" as
reference.
When I use a specific option in the Test solution which require the
unmanaged.dll I get the error "Function _xxxx raised exception 'Unable
to load DLL 'unmanaged.dll': The specified module could not be
found...."

If I add the unmanaged.dll to solution executaion location then it
works fine. Btw, we have used the DllImport to use the unmanaged.dll
which is not COM enabled.

[DllImport("unmanaged.dll", CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]


Have we missed anything? Is there any other alternatives? Sorry to ask
many questions as new to this area of wrapped dlls. Thanks again for
your kind response.

Regards,
M.A
 
Thanks Pavel for your suggestions.

I have performed the steps below but seems the unmanaged.dll still
required by the solution. Any idea?

1. Compile the library.
Example: CSC /platform:x86 /errorreport:prompt /out:"D:\test\bin
\Debug\MySystem.dll" /reference:"C:\WINDOWS\Microsoft.NET\Framework
\v2.0.50727\System.Windows.Forms.dll" /LinkResource:"D:\test
\unmanaged.dll" /target:library "D:\test\CommonTypes.cs" "D:\test
\Condition.cs" "D:\test\ConditionStatus.cs" /keyfile:"D:\test\Key.snk"

2. Add the "MySystem.dll" to GAC

3. In my Tester solution, add the shared GAC - "MySystem.dll" as
reference.
When I use a specific option in the Test solution which require the
unmanaged.dll I get the error "Function _xxxx raised exception 'Unable
to load DLL 'unmanaged.dll': The specified module could not be
found...."

If I add the unmanaged.dll to solution executaion location then it
works fine. Btw, we have used the DllImport to use the unmanaged.dll
which is not COM enabled.

[DllImport("unmanaged.dll", CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]


Have we missed anything? Is there any other alternatives? Sorry to ask
many questions as new to this area of wrapped dlls. Thanks again for
your kind response.

Regards,
M.A
 
Thanks Pavel for your suggestions.

I have performed the steps below but seems the unmanaged.dll still
required by the solution. Any idea?

1. Compile the library.
Example: CSC /platform:x86 /errorreport:prompt /out:"D:\test\bin
\Debug\MySystem.dll" /reference:"C:\WINDOWS\Microsoft.NET\Framework
\v2.0.50727\System.Windows.Forms.dll" /LinkResource:"D:\test
\unmanaged.dll" /target:library "D:\test\CommonTypes.cs" "D:\test
\Condition.cs" "D:\test\ConditionStatus.cs" /keyfile:"D:\test\Key.snk"

2. Add the "MySystem.dll" to GAC

3. In my Tester solution, add the shared GAC - "MySystem.dll" as
reference.
When I use a specific option in the Test solution which require the
unmanaged.dll I get the error "Function _xxxx raised exception 'Unable
to load DLL 'unmanaged.dll': The specified module could not be
found...."

If I add the unmanaged.dll to solution executaion location then it
works fine. Btw, we have used the DllImport to use the unmanaged.dll
which is not COM enabled.

[DllImport("unmanaged.dll", CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]


Have we missed anything? Is there any other alternatives? Sorry to ask
many questions as new to this area of wrapped dlls. Thanks again for
your kind response.

Regards,
M.A
 
Thanks Pavel for your suggestions.

I have performed the steps below but seems the unmanaged.dll still
required by the solution. Any idea?

1. Compile the library.
Example: CSC /platform:x86 /errorreport:prompt /out:"D:\test\bin
\Debug\MySystem.dll" /reference:"C:\WINDOWS\Microsoft.NET\Framework
\v2.0.50727\System.Windows.Forms.dll" /LinkResource:"D:\test
\unmanaged.dll" /target:library "D:\test\CommonTypes.cs" "D:\test
\Condition.cs" "D:\test\ConditionStatus.cs" /keyfile:"D:\test\Key.snk"

2. Add the "MySystem.dll" to GAC

3. In my Tester solution, add the shared GAC - "MySystem.dll" as
reference.
When I use a specific option in the Test solution which require the
unmanaged.dll I get the error "Function _xxxx raised exception 'Unable
to load DLL 'unmanaged.dll': The specified module could not be
found...."

If I add the unmanaged.dll to solution executaion location then it
works fine. Btw, we have used the DllImport to use the unmanaged.dll
which is not COM enabled.

[DllImport("unmanaged.dll", CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]


Have we missed anything? Is there any other alternatives? Sorry to ask
many questions as new to this area of wrapped dlls. Thanks again for
your kind response.

Regards,
M.A
 
MA said:
I have performed the steps below but seems the unmanaged.dll still
required by the solution. Any idea?

1. Compile the library.
Example: CSC /platform:x86 /errorreport:prompt /out:"D:\test\bin
\Debug\MySystem.dll" /reference:"C:\WINDOWS\Microsoft.NET\Framework
\v2.0.50727\System.Windows.Forms.dll" /LinkResource:"D:\test
\unmanaged.dll" /target:library "D:\test\CommonTypes.cs" "D:\test
\Condition.cs" "D:\test\ConditionStatus.cs" /keyfile:"D:\test\Key.snk"

2. Add the "MySystem.dll" to GAC

At this point, can you find unmanaged.dll in the same folder with
MySystem.dll in GAC?
3. In my Tester solution, add the shared GAC - "MySystem.dll" as
reference.

This is interesting, because you can't normally add references right from
the GAC. Or did you rather add reference to the original copy of the
assembly in its Debug folder?

Also, once the reference is added, check that you do _not_ have a copy of
MySystem.dll in the same directory as your Tester.exe when you run the
latter.
 
Thanks "Pavel" for looking at my issue.
At this point, can you find unmanaged.dll in the same folder with
MySystem.dll in GAC?

I can see the MySystem.dll but can not see the unmanaged.dll in GAC. I
thought it is wrapped inside the MySystem.dll so we can not see it. Is
it true?

This is interesting, because you can't normally add references right from
the GAC. Or did you rather add reference to the original copy of the
assembly in its Debug folder?

Sorry, I should have more clear about the references. What I mean is
in VS - IDE "Add references" then select the "MySystem.dll" from
the .NET tab.
Also, once the reference is added, check that you do _not_ have a copy of
MySystem.dll in the same directory as your Tester.exe when you run the latter.

No local copy of MySystem.dll exists in Tester.exe location.

Any suggestions.

Regards,
MA
 
Thanks "Pavel" for looking at my issue.
At this point, can you find unmanaged.dll in the same folder with
MySystem.dll in GAC?

I can see the MySystem.dll but can not see the unmanaged.dll in GAC. I
thought it is wrapped inside the MySystem.dll so we can not see it. Is
it true?

This is interesting, because you can't normally add references right from
the GAC. Or did you rather add reference to the original copy of the
assembly in its Debug folder?

Sorry, I should have more clear about the references. What I mean is
in VS - IDE "Add references" then select the "MySystem.dll" from
the .NET tab.
Also, once the reference is added, check that you do _not_ have a copy of
MySystem.dll in the same directory as your Tester.exe when you run the latter.

No local copy of MySystem.dll exists in Tester.exe location.

Any suggestions.

Regards,
MA
 
MA said:
Thanks "Pavel" for looking at my issue.


I can see the MySystem.dll but can not see the unmanaged.dll in GAC. I
thought it is wrapped inside the MySystem.dll so we can not see it. Is
it true?

No. The point of /linkresource is that you specify an _external_ file as a
dependency for your assembly. It still remains an external file after that.

Perhaps I'll need to clarify what I mean by "see in GAC". When you navigate
to GAC (that is, \WINDOWS\Assembly) in Windows Explorer, it doesn't show you
the true folder structure within - it just shows a flat list of asseblies
(not files/folders). You won't see the unmanaged DLL there. What you need to
do is to either use command line (and chdir & dir), or PowerShell, or some
third-party file manager such as Total Commander or Far to browse GAC, and
find the actual .dll for your assembly within it. And then see whether it'll
have the unmanaged .dll with it, or not.
 
For the record, to view the physical file system sturcture of the
GAC...

GAC in Microsoft .NET framework is implemented via Fusion.dll, which
hides the actual structure of the GAC. To view the physical file
system sturcture of the GAC, create a DWORD entry by the name
DisableCacheViewer under the registry key, HKEY_LOCAL_MACHINE\Software
\Microsoft\Fusion, and set its value to 1. After making the above
modifications to the registry, if you try to open GAC folder, you will
now see the actual structure of GAC."


I have made some changes to the CSC parameters, now I can see in the
GAC the unmanaged.dll in the managed (MySystem.dll). But now my
Tester.exe unable to locate the assembly.

==========================================================
************** Exception Text **************
System.IO.FileNotFoundException: Could not load file or assembly
'MySystem, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8cxxxxf3'
or one of its dependencies. The system cannot find the file specified.
File name: 'MySystem, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=8c4fbxxxxxf3'
==========================================================

Any suggestions?

Regards,
MA
 
For the record, to view the physical file system sturcture of the
GAC...

GAC in Microsoft .NET framework is implemented via Fusion.dll, which
hides the actual structure of the GAC. To view the physical file
system sturcture of the GAC, create a DWORD entry by the name
DisableCacheViewer under the registry key, HKEY_LOCAL_MACHINE\Software
\Microsoft\Fusion, and set its value to 1. After making the above
modifications to the registry, if you try to open GAC folder, you will
now see the actual structure of GAC."


I have made some changes to the CSC parameters, now I can see in the
GAC the unmanaged.dll in the managed (MySystem.dll). But now my
Tester.exe unable to locate the assembly.

==========================================================
************** Exception Text **************
System.IO.FileNotFoundException: Could not load file or assembly
'MySystem, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8cxxxxf3'
or one of its dependencies. The system cannot find the file specified.
File name: 'MySystem, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=8c4fbxxxxxf3'
==========================================================

Any suggestions?

Regards,
MA
 
For the record, to view the physical file system sturcture of the
GAC...

GAC in Microsoft .NET framework is implemented via Fusion.dll, which
hides the actual structure of the GAC. To view the physical file
system sturcture of the GAC, create a DWORD entry by the name
DisableCacheViewer under the registry key, HKEY_LOCAL_MACHINE\Software
\Microsoft\Fusion, and set its value to 1. After making the above
modifications to the registry, if you try to open GAC folder, you will
now see the actual structure of GAC."


I have made some changes to the CSC parameters, now I can see in the
GAC the unmanaged.dll in the managed (MySystem.dll). But now my
Tester.exe unable to locate the assembly.

==========================================================
************** Exception Text **************
System.IO.FileNotFoundException: Could not load file or assembly
'MySystem, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8cxxxxf3'
or one of its dependencies. The system cannot find the file specified.
File name: 'MySystem, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=8c4fbxxxxxf3'
==========================================================

Any suggestions?

Regards,
MA
 
Please ignore my previous post about the unable to locate assmbly. It
was point to the wrong assembly in Tester.

It looks in the right track at this stage. I will do the testing
tomorrow morning and post the update in here. Thanks again for your
advice.

Regards,
MA
 
Back
Top