.NETGURU
Dynamic load assembly problem in asp.net
Messages   Related Types
This message was discovered on microsoft.public.dotnet.framework.
Responses highlighted in red are from those people who are likely to be able to contribute good, authoratitive information to this discussion. They include Microsoft employees, MVP's and others who IMHO contribute well to these kinds of discussions.
Post a new message to this list...

Johnny Hu
i have some code which will dynamic load another assembly
it works fine in WinForm App but got an exception "cannot load the assembly"
when i put it in a WebService App

Loader.AssemblyLoader al = null;
object[] parms = { AssemblyName }; // string AssebmlyName
al = (Loader.AssemblyLoader)domain.CreateInstanceFromAndUnwrap(
"Loader.dll", "Loader.AssemblyLoader", true, bindings, null, parms,
null, null, null); //exception here

can anyone tell me the reason and the solution ?

Reply to this message...
 
    
Steven Cheng[MSFT] (VIP)
Hi Johnny,

Generally, if we correctly load an assembly in winform application but
failed in web app, the problem is likely caused by security issue. Is there
any detailed error info which indicate that there is securty problem?

Also, where do you put the assembly? In ASP.NET , the normal assembly
should be put in the web application's private "bin" folder , if it's
strong-named ones, you should put them in GAC.

Regards,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)

Get Preview at ASP.NET whidbey
http://msdn.microsoft.com/asp.net/whidbey/default.aspx

Reply to this message...
 
    
Johnny Hu
i have tried to sign the Bin folder's full control to networkservice aspnet
everyone internetuser,
and i got the same error (windows 2003)

the Loader.dll is in Bin folder , and the Loader.dll will load another
assembly in another folder.
does it matter ?

you can track my previous post to find out what am i trying to do
http://www.developersdex.com/asp/message.asp?p=2912&ID=%3CeJ1binPZEHA%2E3512%40TK2MSFTNGP12%2Ephx%2Egbl%3E

*****Full Code Below***********

// Loader.cs
// Compile Loader.cs into Loader.dll
using System;
using System.Reflection;
using System.Runtime.Serialization;
namespace Loader
{
// container for assembly and exposes a GetObject function
// to create a late-bound object for casting by the consumer
// this class is meant to be contained in a separate appDomain
// controlled by ObjectLoader class to allow for proper encapsulation
// which enables proper shadow-copying functionality.
public class AssemblyLoader : MarshalByRefObject, IDisposable
{

#region class-level declarations
private Assembly assembly = null;

private CAssemblyInfo assemblyInfo;
public CAssemblyInfo AssemblyInfo
{
get{return assemblyInfo;}
}
#endregion

#region constructors and destructors
public AssemblyLoader( string fullPath )
{
if( assembly == null )
{
assembly = Assembly.LoadFrom( fullPath );

assemblyInfo = new CAssemblyInfo();
assemblyInfo.fullName = assembly.FullName;
assemblyInfo.version = assembly.GetName().Version;
}
}

~AssemblyLoader()
{
dispose( false );
}

public void Dispose()
{
dispose( true );
}

private void dispose( bool disposing )
{
if( disposing )
{
assembly = null;
assemblyInfo = null;
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
System.GC.Collect( 0 );
}
}
#endregion
//object GetObject ()
//{
// i delete this function for i don't need it.
//}
}
[Serializable]
public class CAssemblyInfo
{
public CAssemblyInfo()
{
}
internal string fullName;
public string FullName
{
get{return fullName;}
}
internal Version version;
public Version Version
{
get{return version;}
}
}
}

// ObjectLoader.cs and WebService.asmx is in the same project
// ObjectLoader.cs
using System;
using System.Reflection;
using System.Collections;
namespace Loader
{
/* contains assembly loader objects, stored in a hash
* and keyed on the .dll file they represent. Each assembly loader
* object can be referenced by the original name/path and is used to
* load objects, returned as type Object. It is up to the calling class
* to cast the object to the necessary type for consumption.
* External interfaces are highly recommended!!
* */
public class AssemblyInfoHelper : IDisposable
{
public AssemblyInfoHelper() {/*...*/}

private AppDomainSetup setup;
private AppDomain domain;
private Loader.CAssemblyInfo assemblyInfo;

public Loader.CAssemblyInfo GetAssemblyinfo(string AssemblyName)
{
Loader.AssemblyLoader al = null;

setup = new AppDomainSetup();
setup.ShadowCopyFiles = "true";

domain = AppDomain.CreateDomain( AssemblyName, null, setup );

BindingFlags bindings = BindingFlags.CreateInstance |
BindingFlags.Instance | BindingFlags.Public;
object[] parms = { AssemblyName };
al = (Loader.AssemblyLoader)domain.CreateInstanceFromAndUnwrap(
"Loader.dll", "Loader.AssemblyLoader", true, bindings, null, parms,
null, null, null);

assemblyInfo = al.AssemblyInfo;
AppDomain.Unload(domain);
return assemblyInfo;
}

~AssemblyInfoHelper()
{
dispose( false );
}

public void Dispose()
{
dispose( true );
}

private void dispose( bool disposing )
{
if( disposing )
{
if (domain != null)
AppDomain.Unload(domain);
}
}
}
}

//WebService.asmx
[WebMethod]
public string GetVersion()
{
Loader.AssemblyInfoHelper ai = new Loader.AssemblyInfoHelper();
string ver = "";
try
{
// get the assembly version info with the physical path
// and the assembly will be unloaded with the separate appDomain
// so i can update the assembly anytime,otherwise i have to manully
// stop the w3p.exe process and will cause other WebApp crash
// this code works in a winform app
ver = ai.GetAssemblyinfo(@"C:\MyAssembly.exe").Version.ToString();
}
catch (Exception ex)
{
return ex.Message;
}
return ver;
}

Reply to this message...
 
    
Steven Cheng[MSFT] (VIP)
Hi Johnny,

After some test, I've repro the problem you mentioned, and from the asp.net
exception page, it seems that the runtime will always try locating the
assembly in the
{sys dir}:\windows\system32\inetsrv\

rather than the path we set in the AppDomain's AppDomainSetup object.
Anyway, I"m currently consulting some further experts on this and will
reply you when I got any new information.
Thanks for your understanding.

Regards,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)

Get Preview at ASP.NET whidbey
http://msdn.microsoft.com/asp.net/whidbey/default.aspx

Reply to this message...
 
    
Steven Cheng[MSFT] (VIP)
Hi Johnny,

After some further research, I think we've got the root cause. I'll explain
it detailed here:

In fact, the problems is that we incorrectly use the
AppDomain.CreateInstanceFromAndUnwrap function,

we should use the AppDomain.CreateInstanceAndUnwrap instead.

The difference between the two functions are just like the difference
between Assembly.Load and Assembly.LoadFrom.
Load will search the assembly obey the .net 's assembly locating rules.
From GAC to private bin path...
But the LoadFrom instead, will not. It require the caller to provide a full
path of the assembly such as
LoadFrom("c:\folder\test.dll") , if we don't provide a absolute full path,
it will use the current directory ("Environment.CurrentDirectory").

So as for our issue, we have to alternative means:
1. Use the AppDomain.CreateInstanceAndUnwrap instead of
AppDomain.CreateInstanceFromAndUnwrap , that will make the runtime to
locate the assembly in the privatebin path we specified in the appdomain's
setup info.

#note :
Another thing I'd like to point out is that the setup info's
"PrivateBinPath" is not a absolute path, it should be a subfolder name
which will be combined with the appdomain's basedirectory path so that
generate the whole runtime search path, for example:

string appbase = string appbase = Server.MapPath("~/");
setup.ApplicationBase = appbase + "Addins";
setup.PrivateBinPath = "bin";

2. Still use the AppDomain.CreateInstanceFromAndUnwrap, but we should
specify the full path of the assembly, for example:

util = (CSLib.CSUtil)appDomain.CreateInstanceFromAndUnwrap(appbase +
"Addins\\bin\\"+"CSLib.dll", "CSLib.CSUtil");

Please have a look at the above suggestions. Hope they will help. Thanks.

Regards,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)

Get Preview at ASP.NET whidbey
http://msdn.microsoft.com/asp.net/whidbey/default.aspx

Reply to this message...
 
    
Johnny Hu
thank you for the tips,
i will do some test on that.

[Original message clipped]

Reply to this message...
 
    
Steven Cheng[MSFT] (VIP)
Hi Johnny,

Have you got any updates on this issue or have you figured it out via the
suggestions in my last reply? IF you still have anything unclear , please
feel free to post here. Thanks.

Regards,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)

Get Preview at ASP.NET whidbey
http://msdn.microsoft.com/asp.net/whidbey/default.aspx

Reply to this message...
 
    
Johnny Hu
i am using another simple method, works at this time.

i wonder there is some way i can read version info from a standard .exe
file.
when using windows explorer, there is version info on status bar when the
focus is on a file.

string ver;
Byte[] asmBytes;
BinaryReader reader = new BinaryReader(new FileStream(
Server.MapPath(".\\bin\\Test.exe",
FileMode.Open, FileAccess.Read));

asmBytes = new Byte[reader.BaseStream.Length];
reader.Read(asmBytes, 0, (Int32) reader.BaseStream.Length);
reader.Close();
reader = null;

AppDomain dom = AppDomain.CreateDomain("NewDomain",
AppDomain.CurrentDomain.Evidence, AppDomain.CurrentDomain.SetupInformation);
Assembly asm = dom.Load(asmBytes);
ver = asm.GetName().Version.ToString();
AppDomain.Unload(dom);

[Original message clipped]

Reply to this message...
 
    
Steven Cheng[MSFT] (VIP)
Hi Johnny,

Yes, generally if we want to get an certain assembies's version info, we
can use the reflection api . Such as
Assemly.Getname().Version . Also, there are means to get the fileversion
info. Here is blog thread discussing on this:

#How to get the assembly version and file version of your own assembly?
http://blogs.msdn.com/junfeng/archive/2004/02/28/81407.aspx

Hope also helpful.

Regards,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)

Reply to this message...
 
    
David Levine
Look at fuslogvw.exe and see why it did not load the assembly. My guess is
that the path to the dll is incorrect for the environment it is running in.

"Johnny Hu" <Click here to reveal e-mail address> wrote in message
news:uApMO%Click here to reveal e-mail address...
[Original message clipped]

Reply to this message...
 
    
Johnny Hu
i have already tested it with a physical path
if the system cannot find the dll, different exception will be got.

[Original message clipped]

Reply to this message...
 
    
David Levine
As another poster pointed out, CreateInstanceFromAndUnwrap() uses a full
path and CreateInstanceAndUnwrap uses the 4part assembly name. Looking in
fuslogvw at a load failure makes it instantly obvious why it could not find
the assembly in question - it might be an incorrect assembly name, or the
assembly is not in the path probed. Fuslog is a valuable tool for tracking
down the cause of these problems.

"Johnny Hu" <Click here to reveal e-mail address> wrote in message
news:u$Click here to reveal e-mail address...
[Original message clipped]

Reply to this message...
 
    
David Jessee
What does the exception say? Can you post the stack trace and the message?

"Johnny Hu" <Click here to reveal e-mail address> wrote in message
news:uApMO%Click here to reveal e-mail address...
[Original message clipped]

Reply to this message...
 
    
Johnny Hu
the exception is:
"File or assembly name Loader.dll, or one of its dependencies, was not
found."

just exception above, there is no call stack message.

> What does the exception say? Can you post the stack trace and the
message?
[Original message clipped]

Reply to this message...
 
    
Johnny Hu
i think i have to re-present the problem

1,when the file path is not right, the exception will be
"File or assembly name Loader.dll, or one of its dependencies, was not
found."

2,after using a physical path , still error
"Loader.dll cannot be loaded"
and i got stack trace in watch window :
"System.IO.FileLoadException"
Server stack trace:
at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase,
Boolean isStringized, Evidence assemblySecurity, Boolean
throwOnFileNotFound, Assembly locationHint, StackCrawlMark& stackMark)
at System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Boolean
stringized, Evidence assemblySecurity, StackCrawlMark& stackMark)
at System.Reflection.Assembly.LoadFrom(String assemblyFile, Evidence
securityEvidence, Byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm)
at System.Activator.CreateInstanceFrom(String assemblyFile, String typeName,
Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args,
CultureInfo culture, Object[] activationAttributes, Evidence securityInfo)
at System.AppDomain.CreateInstanceFrom(String assemblyFile, String typeName,
Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args,
CultureInfo culture, Object[] activationAttributes, Evidence
securityAttributes)
at System.AppDomain.CreateInstanceFromAndUnwrap(String assemblyName, String
typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder,
Object[] args, CultureInfo culture, Object[] activationAttributes, Evidence
securityAttributes)
at
System.Runtime.Remoting.Messaging.StackBuilderSink.PrivateProcessMessage(Met
hodBase mb, Object[] args, Object server, Int32 methodPtr, Boolean
fExecuteInContext, Object[]& outArgs)
at
System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessa
ge msg, Int32 methodPtr, Boolean fExecuteInContext)
Exception rethrown at [0]:

[Original message clipped]

Reply to this message...
 
 
System.Activator
System.AppDomain
System.AppDomainSetup
System.Byte
System.Configuration.Assemblies.AssemblyHashAlgorithm
System.Environment
System.GC
System.Globalization.CultureInfo
System.IDisposable
System.IO.BinaryReader
System.IO.FileAccess
System.IO.FileLoadException
System.IO.FileMode
System.IO.FileStream
System.MarshalByRefObject
System.Reflection.Assembly
System.Reflection.AssemblyName
System.Reflection.BindingFlags
System.Web.Services.WebService




ExamGuru IT Solutions - .Net Guru is owned and operated by ExamGuru, Inc., the man behind .Net Guru. If you're in the market for bespoke software or software consultancy, why not get him and his highly trained team to help? - www.examguru.net/ITCertification
Ad


Need Dot Net Interview Questions?
Ask ExamGuru, Inc. for advice and help on Passing .Net Interviews
.Net Projects
Best-of-breed application framework for .NET projects, developed by ExamGuru, Inc. and ExamGuru IT
Free .net Help
Commission ExamGuru, Inc. and his team for your next bespoke software project
FogBUGZ
The only bug tracking system carefully crafted with one goal in mind: helping teams create great software.
Awesome Tools
If you don't know about these, you're missing out... IT Certification Questions
IT Interview Questions
Free Oracle 10g Training
MCSE Boortcamp
Cisco Study Guides
Cheap Study Guides
Exact Questions
Dot Net Interview Questions
Oracle OCP
Cheap Travel
Designer Perfumes - Wholesale Prices
Free Programming Tutorials
 
ExamGuru IT Solutions - .Net Guru is owned and operated by ExamGuru, Inc., the man behind .Net Guru. If you're in the market for bespoke software or software consultancy, why not get him and his highly trained team to help? - www.examguru.net/ITCertification
 Copyright © ExamGuru, Inc. 2001-2006
Contact Us - Terms of Use - Privacy Policy - www.dot-net-guru.com - www.examguru.net - www.oraclesource.net - www.itinterviews.net - www.examguru.net/ITCertification