none
Problem/Questions loading assembly RRS feed

  • Question

  • Hi all.
    I'm sorry if this question has been asked previously but I've searched the forums and I didn't found the exact problem I'm having, so here it is:
    I'm developing an application that will rip another application GUI to create a model of it. The applications I'm trying to rip are only Windows Dorms applications but it really doesn't matter at the moment.

    I was doing the following with relative success:

    1    Assembly aut = Assembly.LoadFile(filePath); 
    2    object entry = aut.CreateInstance(aut.EntryPoint.ToString()); 
    3    aut.EntryPoint.Invoke(entry, new object[] { }); 

    This will effectively execute the application with only one problem: It will try to get the configuration files to my project's directory instead of the directory were the file is. Well I just have to change the working directory to the file's directory, I thought. But this is proving more difficult then I thought. Here is what I'm trying to do: create an AppDomain with AppBasePath equal to the file's directory and load the assembly from this AppDomain. Here is the source:

    1    Evidence policy = new Evidence(AppDomain.CurrentDomain.Evidence);  
    2    AppDomain autDomain = AppDomain.CreateDomain("AUTDomain", policy, filePath.Substring(0, filePath.LastIndexOf('\\')+1), filePath.Substring(0, filePath.LastIndexOf('\\')+1),false);  
    3    AssemblyName autName = AssemblyName.GetAssemblyName(filePath);  
    4    Assembly aut = autDomain.Load(autName);  
    5    object entry = aut.CreateInstance(aut.EntryPoint.ToString());  
    6    aut.EntryPoint.Invoke(entry, new object[] { });  


    The problem is that on line 4 when I try to load the assembly through autDomain I get a FileNotFound Exceptiom. I've double checked the path and the path is correct. The strange thing (maybe just for me that am starting to program in .Net) is that if I simply execute it from a plain AppDomain, i.e

    1    AppDomain autDomain = AppDomain.CreateDomain("AUTDomain"
    2    autDomain.ExecuteAssembly(filePath);  

    The assembly is executed without any problem (even the one I was having in the first place).
    How can I load the assembly from the appDomain I've created?

    TIA
    Jose Tavares
    Thursday, September 18, 2008 2:13 PM

Answers

All replies

  • The appRelativeSearchPath should not be a full path, just the name of a subdirectory (i.e, not c:\program files\yourcompany\yourapp\subdir" but just "subdir").  Pass null if you don't have a meaningful value for it.  However, that' probably not the real problem.  Trouble-shoot this with the Fuslogvw.exe utility.  Post the log if you can't sort it out.
    Hans Passant.
    Thursday, September 18, 2008 5:18 PM
    Moderator
  • Well, the log indeed provided valuable information, thanks for the tip.
    Well but I really don't know what's happening. In the Log the AppBase is the directory of the project but in the debugger the AppBase of autDomain is the path of the application I'm trying to assembly (let's call it AUT) (I want to maintain this usage because my application is supposed to rip any application and it isn't practical to copy the AUT to my project directory every time I want to rip it).
    Remember I'm trying to use the second snippet of code posted above.

    Here is the log:
    *** Assembly Binder Log Entry  (19-09-2008 @ 10:07:27) ***

    The operation failed.
    Bind result: hr = 0x80070002. The system cannot find the file specified.

    Assembly manager loaded from: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll
    Running under executable C:\Documents and Settings\telbit\My Documents\Visual Studio 2008\Projects\GUIRobotPrototype\GUIRobotPrototype\bin\Debug\GUIRobotPrototype.vshost.exe
    --- A detailed error log follows.

    === Pre-bind state information ===
    LOG: User = TELBIT-PC0007\telbit
    LOG: DisplayName = reml-ref, Version=0.8.0.0, Culture=neutral, PublicKeyToken=null
    (Fully-specified)
    LOG: Appbase = file:///C:/Documents and Settings/telbit/My Documents/Visual Studio 2008/Projects/GUIRobotPrototype/GUIRobotPrototype/bin/Debug/
    LOG: Initial PrivatePath = NULL
    LOG: Dynamic Base = NULL
    LOG: Cache Base = NULL
    LOG: AppName = NULL
    Calling assembly : (Unknown).
    ===
    LOG: This bind starts in default load context.
    LOG: No application configuration file found.
    LOG: Using machine configuration file from C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\config\machine.config.
    LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
    LOG: Attempting download of new URL file:///C:/Documents and Settings/telbit/My Documents/Visual Studio 2008/Projects/GUIRobotPrototype/GUIRobotPrototype/bin/Debug/reml-ref.DLL.
    LOG: Attempting download of new URL file:///C:/Documents and Settings/telbit/My Documents/Visual Studio 2008/Projects/GUIRobotPrototype/GUIRobotPrototype/bin/Debug/reml-ref/reml-ref.DLL.
    LOG: Attempting download of new URL file:///C:/Documents and Settings/telbit/My Documents/Visual Studio 2008/Projects/GUIRobotPrototype/GUIRobotPrototype/bin/Debug/reml-ref.EXE.
    LOG: Attempting download of new URL file:///C:/Documents and Settings/telbit/My Documents/Visual Studio 2008/Projects/GUIRobotPrototype/GUIRobotPrototype/bin/Debug/reml-ref/reml-ref.EXE.
    LOG: All probing URLs attempted and failed.

    Friday, September 19, 2008 9:17 AM
  • "Policy not being applied", that's not good.  From the Remarks section of the MSDN topic for AppDomain.Load(AssemblyName):

    This method should only be used to load an assembly into the current application domain. This method is defined for interoperability callers who cannot call the static Load method.

    Hans Passant.
    • Marked as answer by Zhi-Xin Ye Wednesday, September 24, 2008 10:46 AM
    • Unmarked as answer by jpsstavares Friday, September 26, 2008 2:13 PM
    Friday, September 19, 2008 10:11 AM
    Moderator
  • Ok.. not good at all...
    But if I'm able to load the assembly with Assembly.LoadFile, isn't there a way to set the execution path to the directory were the executable file is? can't I create an AppDomain in another directory and load the Assembly from there? is the problem in the Evidence I provide (I'm trying to find a good place to learn about Evidence)?

    I've just tried to load the assembly through Assembly.LoadFrom which according to the MSDN: LoadFile does not load files into the LoadFrom context, and does not resolve dependencies using the load path, as the LoadFrom method does. But the result is the same, i.e., the application tries to load its settings from the Project directory instead of the directory were the assembly is.

    Thanks
    José Tavares
    Friday, September 19, 2008 12:31 PM
  • Update on this problem:

    I'm working with code sample #2 in the first post which gave the log of my second post.
    I've tried to use AppDomain.CurrentDomain.AppendPrivatePath(filePath.Substring(0, filePath.LastIndexOf('\\') + 1)); before I create the Assembly Name i.e:

    1    AppDomainSetup setup = new AppDomainSetup(); 
    2    setup.ApplicationBase = filePath.Substring(0, filePath.LastIndexOf('\\') + 1); 
    3    setup.PrivateBinPath = filePath.Substring(0, filePath.LastIndexOf('\\') + 1); 
    4    Evidence policy = new Evidence(AppDomain.CurrentDomain.Evidence); 
    5    AppDomain autDomain = AppDomain.CreateDomain("AUTDomain", policy, setup); 
    6    AppDomain.CurrentDomain.AppendPrivatePath(filePath.Substring(0, filePath.LastIndexOf('\\') + 1)); 
    7    AssemblyName autName = AssemblyName.GetAssemblyName(filePath); 
    8    Assembly aut = autDomain.Load(autName); 

    And now the log error is:
    *** Assembly Binder Log Entry  (26-09-2008 @ 15:07:20) ***

    The operation failed.
    Bind result: hr = 0x80070002. The system cannot find the file specified.

    Assembly manager loaded from: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll
    Running under executable C:\Documents and Settings\telbit\My Documents\Visual Studio 2008\Projects\GUIRobotPrototype\GUIRobotPrototype\bin\Debug\GUIRobotPrototype.vshost.exe
    --- A detailed error log follows.

    === Pre-bind state information ===
    LOG: User = TELBIT-PC0007\telbit
    LOG: DisplayName = reml-ref, Version=0.8.0.0, Culture=neutral, PublicKeyToken=null
    (Fully-specified)
    LOG: Appbase = file:///C:/Documents and Settings/telbit/My Documents/Visual Studio 2008/Projects/GUIRobotPrototype/GUIRobotPrototype/bin/Debug/
    LOG: Initial PrivatePath = D:\Tests\CS\remlref\
    LOG: Dynamic Base = NULL
    LOG: Cache Base = NULL
    LOG: AppName = NULL
    Calling assembly : (Unknown).
    ===
    LOG: This bind starts in default load context.
    LOG: Using application configuration file: C:\Documents and Settings\telbit\My Documents\Visual Studio 2008\Projects\GUIRobotPrototype\GUIRobotPrototype\bin\Debug\GUIRobotPrototype.vshost.exe.Config
    LOG: Using machine configuration file from C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\config\machine.config.
    LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
    WRN: Not probing location file:///D:/Tests/CS/remlref/reml-ref.DLL, because the location falls outside of the appbase.
    WRN: Not probing location file:///D:/Tests/CS/remlref/reml-ref/reml-ref.DLL, because the location falls outside of the appbase.
    WRN: Not probing location file:///D:/Tests/CS/remlref/reml-ref.EXE, because the location falls outside of the appbase.
    WRN: Not probing location file:///D:/Tests/CS/remlref/reml-ref/reml-ref.EXE, because the location falls outside of the appbase.
    LOG: Attempting download of new URL file:///C:/Documents and Settings/telbit/My Documents/Visual Studio 2008/Projects/GUIRobotPrototype/GUIRobotPrototype/bin/Debug/reml-ref.DLL.
    LOG: Attempting download of new URL file:///C:/Documents and Settings/telbit/My Documents/Visual Studio 2008/Projects/GUIRobotPrototype/GUIRobotPrototype/bin/Debug/reml-ref/reml-ref.DLL.
    LOG: Attempting download of new URL file:///C:/Documents and Settings/telbit/My Documents/Visual Studio 2008/Projects/GUIRobotPrototype/GUIRobotPrototype/bin/Debug/reml-ref.EXE.
    LOG: Attempting download of new URL file:///C:/Documents and Settings/telbit/My Documents/Visual Studio 2008/Projects/GUIRobotPrototype/GUIRobotPrototype/bin/Debug/reml-ref/reml-ref.EXE.
    LOG: All probing URLs attempted and failed.
    Now there is a warning explicitly saying it won't try the path I gave to it because it's outside the appbase.
    Two questions:
        1: It appears that the assembly is trying to be loaded in the CurrentAppDomain instead of in the AppDomain I've created. Is the problem the scope in which AssemblyDomain is being created? If so how can I create the AssemblyName in the scope of the AppDomain I've created?
        2: Is there any way to allowing the probing outside the AppBase?

    TIA,
    José Tavares
    Friday, September 26, 2008 2:18 PM
  • This is not going to get any better until you stop using AppDomain.Load().
    Hans Passant.
    Friday, September 26, 2008 2:56 PM
    Moderator
  • So do you have any suggestions?
    My application is a GUI Ripper application that executes an application for test (AUT) and tries to map all the components AUT have. The problem I'm having is that using this code:
    1Assembly aut = Assembly.LoadFile(filePath);  
    2object entry = aut.CreateInstance(aut.EntryPoint.ToString());  
    3aut.EntryPoint.Invoke(entry, new object[] { });  

    AUT launches but tries to load the resources it needs from my AppBase instead of the directory the AUT remains. Any help on how to do this?

    I've tried another approach using UI Atomation. With UI Automation I launch a process and then get the windows of that process. The problem is that the AutomationElements don't give all the information I need (menuitems of a menu when closed or items disabled, for example) and I can't convert an AutomationElement into the corresponding WinForm Control.

    I've done the same thing with java apps and all it took was to read the jar file execute an instance of the main class and from there I was able to retrieve all the gui components of the application. Isn't there a similar way to do this in C#?

    Thanks
    Friday, September 26, 2008 3:11 PM
  • Use AppDomain.CreateInstanceAndUnwrap().
    Hans Passant.
    Friday, September 26, 2008 7:32 PM
    Moderator