How to List All Required Assemblies for an EXE

  • Thread starter Thread starter Charles Law
  • Start date Start date
C

Charles Law

I'm sorry to keep harping on about this one, but it is really quite
important for me to be able to list _all_ required assemblies in my Help
About box. Herfried kindly posted some code before that lists _loaded_
assemblies and their version, but I have one assembly that is not loaded
until the user has done something quite specific in the program, and I need
to list this one too. Other applications seem to manage it, so I wonder how
it can be done in .NET.

Furthermore, the code I have at present does not locate the assembly. I also
need to be able to do this so that I can be certain that all assemblies are
being loaded from the right place.

Can anyone help?

TIA

Charles
 
Charles,
I have a C# application that does something similar (I think) to what
you're wanting. I'll paste the specific code below. The code is in C#
but should be easily converted to VB.NET. HTH

Jason Newell, MCAD
Software Engineer


###############################################################################
private static bool PreloadAssemblies()
{
Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();

AssemblyName[] assemblies = assembly.GetReferencedAssemblies();

foreach (AssemblyName assemblyName in assemblies)
{
try
{
Assembly.Load(assemblyName);
}
catch (System.IO.FileNotFoundException)
{
MessageBox.Show(
"Assembly " + assemblyName.Name + " was not found.",
"File Not Found",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
catch (System.BadImageFormatException)
{
MessageBox.Show(
"Assembly " + assemblyName.Name + " is an invalid file image.",
"Bad Image Format",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
catch (System.Security.SecurityException)
{
MessageBox.Show(
"You do not have rights to assembly " + assemblyName.Name + ".",
"Security Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
catch (System.Exception)
{
MessageBox.Show(
"Assembly " + assemblyName.Name + " cannot be loaded.",
"Assembly Load Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
}
return true;
}
###############################################################################
 
Hi Jason

Thanks for the response. I have converted and run the code you posted but I
don't seem to be quite there yet. I think my problem can be explained as
follows

I have a hierarchy of assemblies like this

MainApp -> SubAssembly1
-> SubAssembly2
-> SubAssembly3 -> SubAssembly4
-> SubAssembly5

If I list the referenced assemblies after preloading I get SubAssembly1,
SubAssembly2, SubAssembly3, and SubAssembly5, but not SubAssembly4.

Can you think of a way to get at SubAssembly4? Also, I still don't seem to
be able to identify where each assembly was loaded from.

Charles


Jason Newell said:
Charles,
I have a C# application that does something similar (I think) to what
you're wanting. I'll paste the specific code below. The code is in C#
but should be easily converted to VB.NET. HTH

Jason Newell, MCAD
Software Engineer


###############################################################################
private static bool PreloadAssemblies()
{
Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();

AssemblyName[] assemblies = assembly.GetReferencedAssemblies();

foreach (AssemblyName assemblyName in assemblies)
{
try
{
Assembly.Load(assemblyName);
}
catch (System.IO.FileNotFoundException)
{
MessageBox.Show(
"Assembly " + assemblyName.Name + " was not found.",
"File Not Found",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
catch (System.BadImageFormatException)
{
MessageBox.Show(
"Assembly " + assemblyName.Name + " is an invalid file image.",
"Bad Image Format",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
catch (System.Security.SecurityException)
{
MessageBox.Show(
"You do not have rights to assembly " + assemblyName.Name + ".",
"Security Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
catch (System.Exception)
{
MessageBox.Show(
"Assembly " + assemblyName.Name + " cannot be loaded.",
"Assembly Load Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
}
return true;
}
###############################################################################



Charles said:
I'm sorry to keep harping on about this one, but it is really quite
important for me to be able to list _all_ required assemblies in my Help
About box. Herfried kindly posted some code before that lists _loaded_
assemblies and their version, but I have one assembly that is not loaded
until the user has done something quite specific in the program, and I
need to list this one too. Other applications seem to manage it, so I
wonder how it can be done in .NET.

Furthermore, the code I have at present does not locate the assembly. I
also need to be able to do this so that I can be certain that all
assemblies are being loaded from the right place.

Can anyone help?

TIA

Charles
 
Charles,
I'm a little closer with this next code. I'm busy at work so I can't
finish it for you. Maybe this will help you get over the hump.
I converted the PreloadAssembly() method into a recursive method so
that it will traverse the Assembly structure. The problem right now is
it gets into an endless loop. Need some check there to get out of the
loop. Once you have an Assembly object, you can use the CodeBase
property to determine where the assembly is being loaded from. HTH

Jason Newell, MCAD
Software Engineer

####################################################################################
PreloadAssembly(Assembly.GetExecutingAssembly());


static void PreloadAssembly(Assembly assembly)
{
Console.WriteLine(assembly.CodeBase);

AssemblyName[] assemblies = assembly.GetReferencedAssemblies();
foreach (AssemblyName assemblyName in assemblies)
{
Assembly referencedAssembly = Assembly.Load(assemblyName);
PreloadAssembly(referencedAssembly);
}
}

###################################################################################


Charles said:
Hi Jason

Thanks for the response. I have converted and run the code you posted but I
don't seem to be quite there yet. I think my problem can be explained as
follows

I have a hierarchy of assemblies like this

MainApp -> SubAssembly1
-> SubAssembly2
-> SubAssembly3 -> SubAssembly4
-> SubAssembly5

If I list the referenced assemblies after preloading I get SubAssembly1,
SubAssembly2, SubAssembly3, and SubAssembly5, but not SubAssembly4.

Can you think of a way to get at SubAssembly4? Also, I still don't seem to
be able to identify where each assembly was loaded from.

Charles


Charles,
I have a C# application that does something similar (I think) to what
you're wanting. I'll paste the specific code below. The code is in C#
but should be easily converted to VB.NET. HTH

Jason Newell, MCAD
Software Engineer


###############################################################################
private static bool PreloadAssemblies()
{
Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();

AssemblyName[] assemblies = assembly.GetReferencedAssemblies();

foreach (AssemblyName assemblyName in assemblies)
{
try
{
Assembly.Load(assemblyName);
}
catch (System.IO.FileNotFoundException)
{
MessageBox.Show(
"Assembly " + assemblyName.Name + " was not found.",
"File Not Found",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
catch (System.BadImageFormatException)
{
MessageBox.Show(
"Assembly " + assemblyName.Name + " is an invalid file image.",
"Bad Image Format",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
catch (System.Security.SecurityException)
{
MessageBox.Show(
"You do not have rights to assembly " + assemblyName.Name + ".",
"Security Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
catch (System.Exception)
{
MessageBox.Show(
"Assembly " + assemblyName.Name + " cannot be loaded.",
"Assembly Load Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
}
return true;
}
###############################################################################



Charles said:
I'm sorry to keep harping on about this one, but it is really quite
important for me to be able to list _all_ required assemblies in my Help
About box. Herfried kindly posted some code before that lists _loaded_
assemblies and their version, but I have one assembly that is not loaded
until the user has done something quite specific in the program, and I
need to list this one too. Other applications seem to manage it, so I
wonder how it can be done in .NET.

Furthermore, the code I have at present does not locate the assembly. I
also need to be able to do this so that I can be certain that all
assemblies are being loaded from the right place.

Can anyone help?

TIA

Charles
 
Hi Jason

Great minds ... I tried making it recursive before I posted back last time,
and hit exactly the same problem. It seems like there are circular
references amongst the Microsoft assemblies, which is unfortunate.

Thanks for looking at it again.

Charles


Jason Newell said:
Charles,
I'm a little closer with this next code. I'm busy at work so I can't
finish it for you. Maybe this will help you get over the hump.
I converted the PreloadAssembly() method into a recursive method so that
it will traverse the Assembly structure. The problem right now is it gets
into an endless loop. Need some check there to get out of the loop. Once
you have an Assembly object, you can use the CodeBase property to
determine where the assembly is being loaded from. HTH

Jason Newell, MCAD
Software Engineer

####################################################################################
PreloadAssembly(Assembly.GetExecutingAssembly());


static void PreloadAssembly(Assembly assembly)
{
Console.WriteLine(assembly.CodeBase);

AssemblyName[] assemblies = assembly.GetReferencedAssemblies();
foreach (AssemblyName assemblyName in assemblies)
{
Assembly referencedAssembly = Assembly.Load(assemblyName);
PreloadAssembly(referencedAssembly);
}
}

###################################################################################


Charles said:
Hi Jason

Thanks for the response. I have converted and run the code you posted but
I don't seem to be quite there yet. I think my problem can be explained
as follows

I have a hierarchy of assemblies like this

MainApp -> SubAssembly1
-> SubAssembly2
-> SubAssembly3 -> SubAssembly4
-> SubAssembly5

If I list the referenced assemblies after preloading I get SubAssembly1,
SubAssembly2, SubAssembly3, and SubAssembly5, but not SubAssembly4.

Can you think of a way to get at SubAssembly4? Also, I still don't seem
to be able to identify where each assembly was loaded from.

Charles


Charles,
I have a C# application that does something similar (I think) to what
you're wanting. I'll paste the specific code below. The code is in C#
but should be easily converted to VB.NET. HTH

Jason Newell, MCAD
Software Engineer


###############################################################################
private static bool PreloadAssemblies()
{
Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();

AssemblyName[] assemblies = assembly.GetReferencedAssemblies();

foreach (AssemblyName assemblyName in assemblies)
{
try
{
Assembly.Load(assemblyName);
}
catch (System.IO.FileNotFoundException)
{
MessageBox.Show(
"Assembly " + assemblyName.Name + " was not found.",
"File Not Found",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
catch (System.BadImageFormatException)
{
MessageBox.Show(
"Assembly " + assemblyName.Name + " is an invalid file image.",
"Bad Image Format",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
catch (System.Security.SecurityException)
{
MessageBox.Show(
"You do not have rights to assembly " + assemblyName.Name + ".",
"Security Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
catch (System.Exception)
{
MessageBox.Show(
"Assembly " + assemblyName.Name + " cannot be loaded.",
"Assembly Load Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
}
return true;
}
###############################################################################



Charles Law wrote:

I'm sorry to keep harping on about this one, but it is really quite
important for me to be able to list _all_ required assemblies in my Help
About box. Herfried kindly posted some code before that lists _loaded_
assemblies and their version, but I have one assembly that is not loaded
until the user has done something quite specific in the program, and I
need to list this one too. Other applications seem to manage it, so I
wonder how it can be done in .NET.

Furthermore, the code I have at present does not locate the assembly. I
also need to be able to do this so that I can be certain that all
assemblies are being loaded from the right place.

Can anyone help?

TIA

Charles
 
Charles,
The endless loop can easily be adverted by keeping a list of
Asssemblies that you've already loaded and not trying to load them
twice. I just didn't have time to code it.
Your requirement was to list all required Assemblies with their path,
which is what this does. With the endless loop check implemented,
shouldn't this be your final solution?

Jason Newell, MCAD
Software Engineer


Charles said:
Hi Jason

Great minds ... I tried making it recursive before I posted back last time,
and hit exactly the same problem. It seems like there are circular
references amongst the Microsoft assemblies, which is unfortunate.

Thanks for looking at it again.

Charles


Charles,
I'm a little closer with this next code. I'm busy at work so I can't
finish it for you. Maybe this will help you get over the hump.
I converted the PreloadAssembly() method into a recursive method so that
it will traverse the Assembly structure. The problem right now is it gets
into an endless loop. Need some check there to get out of the loop. Once
you have an Assembly object, you can use the CodeBase property to
determine where the assembly is being loaded from. HTH

Jason Newell, MCAD
Software Engineer

####################################################################################
PreloadAssembly(Assembly.GetExecutingAssembly());


static void PreloadAssembly(Assembly assembly)
{
Console.WriteLine(assembly.CodeBase);

AssemblyName[] assemblies = assembly.GetReferencedAssemblies();
foreach (AssemblyName assemblyName in assemblies)
{
Assembly referencedAssembly = Assembly.Load(assemblyName);
PreloadAssembly(referencedAssembly);
}
}

###################################################################################


Charles said:
Hi Jason

Thanks for the response. I have converted and run the code you posted but
I don't seem to be quite there yet. I think my problem can be explained
as follows

I have a hierarchy of assemblies like this

MainApp -> SubAssembly1
-> SubAssembly2
-> SubAssembly3 -> SubAssembly4
-> SubAssembly5

If I list the referenced assemblies after preloading I get SubAssembly1,
SubAssembly2, SubAssembly3, and SubAssembly5, but not SubAssembly4.

Can you think of a way to get at SubAssembly4? Also, I still don't seem
to be able to identify where each assembly was loaded from.

Charles




Charles,
I have a C# application that does something similar (I think) to what
you're wanting. I'll paste the specific code below. The code is in C#
but should be easily converted to VB.NET. HTH

Jason Newell, MCAD
Software Engineer


###############################################################################
private static bool PreloadAssemblies()
{
Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();

AssemblyName[] assemblies = assembly.GetReferencedAssemblies();

foreach (AssemblyName assemblyName in assemblies)
{
try
{
Assembly.Load(assemblyName);
}
catch (System.IO.FileNotFoundException)
{
MessageBox.Show(
"Assembly " + assemblyName.Name + " was not found.",
"File Not Found",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
catch (System.BadImageFormatException)
{
MessageBox.Show(
"Assembly " + assemblyName.Name + " is an invalid file image.",
"Bad Image Format",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
catch (System.Security.SecurityException)
{
MessageBox.Show(
"You do not have rights to assembly " + assemblyName.Name + ".",
"Security Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
catch (System.Exception)
{
MessageBox.Show(
"Assembly " + assemblyName.Name + " cannot be loaded.",
"Assembly Load Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
}
return true;
}
###############################################################################



Charles Law wrote:


I'm sorry to keep harping on about this one, but it is really quite
important for me to be able to list _all_ required assemblies in my Help
About box. Herfried kindly posted some code before that lists _loaded_
assemblies and their version, but I have one assembly that is not loaded
until the user has done something quite specific in the program, and I
need to list this one too. Other applications seem to manage it, so I
wonder how it can be done in .NET.

Furthermore, the code I have at present does not locate the assembly. I
also need to be able to do this so that I can be certain that all
assemblies are being loaded from the right place.

Can anyone help?

TIA

Charles
 
Jason
Thanks for looking at it again.

I was referring to your earlier review rather than asking you to keep going.
You are right, with the list of loaded assemblies stopping recursion this
should do just what I want.

Thanks again.

Charles


Jason Newell said:
Charles,
The endless loop can easily be adverted by keeping a list of Asssemblies
that you've already loaded and not trying to load them twice. I just
didn't have time to code it.
Your requirement was to list all required Assemblies with their path,
which is what this does. With the endless loop check implemented,
shouldn't this be your final solution?

Jason Newell, MCAD
Software Engineer


Charles said:
Hi Jason

Great minds ... I tried making it recursive before I posted back last
time, and hit exactly the same problem. It seems like there are circular
references amongst the Microsoft assemblies, which is unfortunate.

Thanks for looking at it again.

Charles


Charles,
I'm a little closer with this next code. I'm busy at work so I can't
finish it for you. Maybe this will help you get over the hump.
I converted the PreloadAssembly() method into a recursive method so that
it will traverse the Assembly structure. The problem right now is it
gets into an endless loop. Need some check there to get out of the loop.
Once you have an Assembly object, you can use the CodeBase property to
determine where the assembly is being loaded from. HTH

Jason Newell, MCAD
Software Engineer

####################################################################################
PreloadAssembly(Assembly.GetExecutingAssembly());


static void PreloadAssembly(Assembly assembly)
{
Console.WriteLine(assembly.CodeBase);

AssemblyName[] assemblies = assembly.GetReferencedAssemblies();
foreach (AssemblyName assemblyName in assemblies)
{
Assembly referencedAssembly = Assembly.Load(assemblyName);
PreloadAssembly(referencedAssembly);
}
}

###################################################################################


Charles Law wrote:

Hi Jason

Thanks for the response. I have converted and run the code you posted
but I don't seem to be quite there yet. I think my problem can be
explained as follows

I have a hierarchy of assemblies like this

MainApp -> SubAssembly1
-> SubAssembly2
-> SubAssembly3 -> SubAssembly4
-> SubAssembly5

If I list the referenced assemblies after preloading I get SubAssembly1,
SubAssembly2, SubAssembly3, and SubAssembly5, but not SubAssembly4.

Can you think of a way to get at SubAssembly4? Also, I still don't seem
to be able to identify where each assembly was loaded from.

Charles




Charles,
I have a C# application that does something similar (I think) to what
you're wanting. I'll paste the specific code below. The code is in C#
but should be easily converted to VB.NET. HTH

Jason Newell, MCAD
Software Engineer


###############################################################################
private static bool PreloadAssemblies()
{
Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();

AssemblyName[] assemblies = assembly.GetReferencedAssemblies();

foreach (AssemblyName assemblyName in assemblies)
{
try
{
Assembly.Load(assemblyName);
}
catch (System.IO.FileNotFoundException)
{
MessageBox.Show(
"Assembly " + assemblyName.Name + " was not found.",
"File Not Found",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
catch (System.BadImageFormatException)
{
MessageBox.Show(
"Assembly " + assemblyName.Name + " is an invalid file image.",
"Bad Image Format",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
catch (System.Security.SecurityException)
{
MessageBox.Show(
"You do not have rights to assembly " + assemblyName.Name + ".",
"Security Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
catch (System.Exception)
{
MessageBox.Show(
"Assembly " + assemblyName.Name + " cannot be loaded.",
"Assembly Load Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
}
return true;
}
###############################################################################



Charles Law wrote:


I'm sorry to keep harping on about this one, but it is really quite
important for me to be able to list _all_ required assemblies in my
Help About box. Herfried kindly posted some code before that lists
_loaded_ assemblies and their version, but I have one assembly that is
not loaded until the user has done something quite specific in the
program, and I need to list this one too. Other applications seem to
manage it, so I wonder how it can be done in .NET.

Furthermore, the code I have at present does not locate the assembly.
I also need to be able to do this so that I can be certain that all
assemblies are being loaded from the right place.

Can anyone help?

TIA

Charles
 
One possible problem with your approach is that you are loading the
assemblies into memory and there is no way to unload them.

You might wish to create an AppDomain and enumerate your assemblies
with that then you can call it's UnloadDomain method to unload any
assemblies that you loaded.

Chris
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top