2016-06-07 28 views
3

Ich lade eine Funktion auf neu erstellte AppDomain und alle Arbeit ist in Ordnung, aber wenn ich Programm schließe und dann umbenennen und neu starten, dann habe ich FileNotFound Ausnahme. Ich verstehe es einfach nicht, wie kann das sein?AppDomain DoCallBack FileNotFound Ausnahme

Fehler (appDomainProject ursprünglichen Programmname)

System.IO.FileNotFoundException: Could not load file or assembly "appDomainProject, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null" or one of its dependencies. Can not find the file specified. 

Quelle

using System; 
using System.IO; 
using System.Windows.Forms; 

namespace appDomainProject 
{ 
    static class Program 
    { 
     /// <summary> 
     /// The main entry point for the application. 
     /// </summary> 
     [STAThread] 
     static void Main() 
     { 
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 

      try 
      { 
       AppDomain authDomain = AppDomain.CreateDomain(DateTime.Now.ToString()); 
       authDomain.DoCallBack(load_Auth); 
      } 
      catch (Exception ex) 
      { 
       File.WriteAllText("e.txt", ex.ToString());; 
       MessageBox.Show(ex.ToString()); 
      } 
     } 

     private static void load_Auth() 
     { 
      MessageBox.Show("AUTH"); 
     } 
    } 
} 
+0

nur um sicher zu sein: „das Programm schließen und benennen Sie es um ", meinen Sie, dass Sie die exe-Datei umbenennen, keine Neuerstellung, keine Registrierung in GAC oder NGen usw.? – dlatikay

+0

yeap, benennen Sie es einfach ohne Umbau – SLI

+0

kann reproduzieren. Fehler in der Quellzeile 21, 'DoCallBack'. Interessanterweise wurde ein Q, das wie ein Duplikat von diesem aussieht, aus SO gelöscht: http://stackoverflow.com/questions/30512932/execute-code-in-appdomain-in-enamed-executables – dlatikay

Antwort

2

verwenden Ich vermute, dass exe s eine Art von fest codierten Namen über sie haben. In der Tat, wenn Sie typeof(Program).AssemblyName überprüfen, ist es der ursprüngliche Name, weshalb ich erwarte, dass wir den Fehler erhalten.

Sie können die DLL jedoch immer manuell in die AppDomain laden und dann eine Klasse darin haben, die die Anfrage nach dem "orginal" Namen abfängt und durch die korrekte Assembly ersetzt.

Dieser Code funktioniert das:

/// <summary> 
/// It seems that if you rename an exe and then try to load said 
/// assembly into a separate app-domain, .NET looks for the original 
/// name. This class loads the current assembly into the app 
/// domain manually and then detects request for the original name 
/// and redirects it to the correct assembly. 
/// 
/// http://stackoverflow.com/questions/37685180 
/// </summary> 
public class RenamedExeFixer : MarshalByRefObject 
{ 
    /// <summary> Load the assembly that this type is in into the app-domain. </summary> 
    public static void LoadOriginatingAssemblyIntoDomain(AppDomain appDomain) 
    { 
    var pathToSelf = new Uri(typeof(RenamedExeFixer).Assembly.CodeBase).LocalPath; 
    appDomain.Load(File.ReadAllBytes(pathToSelf)); 

    // create an instance of the class inside of the domain 
    // so that it can hook into the AssemblyResolve event 
    appDomain.CreateInstanceFrom(pathToSelf, typeof(RenamedExeFixer).FullName); 
    } 

    private readonly string _myAssemblyName; 

    public RenamedExeFixer() 
    { 
    // cached for efficiency (probably not needed) 
    _myAssemblyName = typeof(RenamedExeFixer).Assembly.FullName; 

    AppDomain.CurrentDomain.AssemblyResolve += HandleAssemblyResolve; 
    } 

    private Assembly HandleAssemblyResolve(object sender, ResolveEventArgs args) 
    { 
    if (args.Name == _myAssemblyName) 
    { 
     return typeof(RenamedExeFixer).Assembly; 
    } 

    return null; 
    } 
} 

Und dann alles, was Sie tun müssen, ist die Helfer-Methode aufrufen, nachdem Ihre App-Domain erstellen:

AppDomain authDomain = AppDomain.CreateDomain(DateTime.Now.ToString()); 
RenamedExeFixer.LoadOriginatingAssemblyIntoDomain(authDomain); 
authDomain.DoCallBack(load_Auth); 
0

Sorry, das ist von Entwurf ...

als Behelfslösung können Sie die bewegen Methode zu einer externen DLL, so dass Sie die .exe umbenennen können.

Wenn Sie Ihre Anwendung nur eine Datei sein, können Sie ILmerge

+0

Gibt es eine Quelle für "by design"? – FriendlyGuy

+0

@MackieChan keine Dokumentation, aber wenn Sie den .net-Code betrachten und wenn Sie darüber nachdenken, wofür Docallback ist.Es muss den Namen der exe speichern, um Cross Application Call – giammin

+0

zu tun. Ich denke, was passiert ist, dass es den Assemblynamen speichert, der der ursprüngliche exe-Name ist (wahrscheinlich wegen der Art, wie .NET exes gespeichert wird). Wenn die Baugruppe geladen wird, kann sie daher nicht ordnungsgemäß gelöst werden. Ich weiß nicht, ob ich sagen würde, dass es ein Design ist, sondern dass es ein Nebeneffekt der Arbeitsweise von .NET ist (wenn meine Theorie stimmt). – FriendlyGuy