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.
| 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 ?
|
|
| |
| |
| 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
|
|
| |
| |
| 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; }
|
|
| |
| |
| 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
|
|
| |
| |
| 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
|
|
| |
| |
| Johnny Hu |
thank you for the tips, i will do some test on that.
[Original message clipped]
|
|
| |
| |
| 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
|
|
| |
| |
| 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]
|
|
| |
| |
| 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.)
|
|
| |
|
|
|
|
|
|
|
|
| |
| 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]
|
|
| |
| |
| 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]
|
|
| |
| |
| 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]
|
|
| |
|
|
|
| |
| 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]
|
|
| |
| |
| 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]
|
|
| |
| |
| 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]
|
|
| |
|
|
|
|
|
|
|