[quoted text, click to view] "Boris" <Boris@discussions.microsoft.com> wrote in message
news:C51FC1E8-8D3E-441B-BF2C-0AA7F0F50753@microsoft.com...
>I notice the following strange behavior of the applications running under
> .NET Framework.
>
> Let say I have application MyApp.exe which reference assembly
> MyAssembly.dll.
> The MyAssembly.dll is strong named assembly, which is installed in the
> GAC.
>
> I notice that if MyAssembly.dll is not installed in GAC or the different
> version of MyAssembly.dll is installed in GAC then MyApp.exe starts OK.
> But
> as soon as the MyApp.exe app tries to call any function from the
> MyAssembly.dll the MyApp.exe application crashes.
This is by design. the CLR does delay loading of assemblies to both increase
application startup time and to forgoe the overhead of loading an assembly
that ends up not being used.
[quoted text, click to view] > In unmanaged VC++ 6.0 world the application wouldn't even allowed to start
> if some dll are missing. The system would display error message saying
> that
> some dll's are missing and application would gracefully exit.
Not if you turn on delay loading for a DLL
[quoted text, click to view] > I wonder whether I misunderstand something or made any mistake? Why
> MyApp.exe is allowed to start in order to crash right after attemp to use
> any
> functionality from missing dependent assembly?
>
> I was told that CLR doesn't load anything untill it needs it. OK, but how
> to
> prevent the crash I described above and exit gracefully like in VC++ 6.0
> case?
>
> Can anyone clarify this situation?
> Thanks
Here is some code that will preload your assemblies:
using System;
using System.Reflection;
using System.Collections;
using System.Text;
class App
{
static void Main(string[] args)
{
PleaseSlowDownMyApplicationStartup();
RestOfApplication();
}
static void RestOfApplication()
{
// the rest of the application needs to be
// in another method otherwise the JIT compiler will
// load the assembleis and potentially fail outside of this
// functionality
}
static ArrayList missingAssemblies = new ArrayList();
static void PleaseSlowDownMyApplicationStartup()
{
LoadDependencies(Assembly.GetExecutingAssembly().GetName());
if( missingAssemblies.Count > 0 )
{
throw new AssemblyDependencyException(string.Format("{0} assemblies
were either missing or unloadable", missingAssemblies.Count),
missingAssemblies);
}
}
static void LoadDependencies(AssemblyName name)
{
try
{
Assembly a = Assembly.Load(name);
foreach(AssemblyName depends in a.GetReferencedAssemblies())
{
LoadDependencies(depends);
}
}
catch(Exception)
{
missingAssemblies.Add(name);
}
}
}
class AssemblyDependencyException : Exception
{
public AssemblyDependencyException( string msg, ArrayList
incorrectAssemblies )
: base(msg)
{
incorrect = incorrectAssemblies;
}
ArrayList incorrect;
public override string ToString()
{
StringBuilder sb = new StringBuilder();
foreach( AssemblyName name in incorrect )
{
sb.Append(name.ToString());
sb.Append(Environment.NewLine);
}
return sb.ToString();
}
}
Regards
Richard Blewett - DevelopMentor
http://www.dotnetconsult.co.uk/weblog
http://www.dotnetconsult.co.uk