Dans mon défaut (confiance totale) AppDomain Je veux créer un bac à sable AppDomain et abonnez-vous à un événement dans ce:Pourquoi ne puis-je pas m'abonner à un événement dans un AppDomain de confiance partielle?
class Domain : MarshalByRefObject
{
public event Action TestEvent;
}
Domain domain = AppDomainStarter.Start<Domain>(@"C:\Temp", "Domain", null, true);
domain.TestEvent +=() => { }; // SecurityException
Abonnement échoue avec le message « Demande d'autorisation de type « System.Security. Permissions.ReflectionPermission, mscorlib, Version = 4.0.0.0 ... 'a échoué. "
(Pour la définition de AppDomainStarter, voir my answer to another question.)
Notez que le ApplicationBase
C: \ Temp est pas le dossier qui contient l'assembly qui contient du domaine. C'est délibéré; mon but est de charger un deuxième assembly non approuvé tiers dans le nouveau AppDomain, et ce second assembly est situé dans C: \ Temp (ou ailleurs, peut-être même un partage réseau). Mais avant de pouvoir charger le second assemblage, j'ai besoin de charger ma classe Domain
dans le nouveau AppDomain. Cela réussit, mais pour une raison quelconque, je ne peux pas m'abonner à un événement à travers la limite AppDomain (je peux appeler des méthodes, mais pas m'abonner à des événements). : De toute évidence, lors de l'abonnement à un événement dans un sandbox AppDomain, la méthode de l'abonné et la classe qui contient l'abonné doivent être publiques. Par exemple:
public static class Program
{
class Domain : MarshalByRefObject
{
public event Action TestEvent;
public Domain() { Console.WriteLine("Domain created OK"); }
}
static void Main()
{
string loc = @"C:\Temp";
Domain domain = AppDomainStarter.Start<Domain>(loc, "Domain", null, true);
// DIFFERENT EXCEPTION THIS TIME!
domain.TestEvent += new Action(domain_TestEvent);
}
public static void domain_TestEvent() { }
}
Cependant, je ne peux toujours pas m'abonner à l'événement. La nouvelle erreur est "Impossible de charger le fichier ou l'assemblage 'TestApp, Version = 1.0.0.0, Culture = Neutre, PublicKeyToken = null' ou l'une de ses dépendances.Le système ne trouve pas le fichier spécifié." En un sens, cela a du sens parce que j'ai spécifié le "mauvais" dossier "C: \ Temp" comme ApplicationBase de mon nouvel AppDomain, mais d'une certaine manière cela n'a aucun sens parce que l'assemblage "TestApp" est déjà chargé dans les deux AppDomains. Comment est-il possible que le CLR ne trouve pas un assembly déjà chargé?
De plus, il ne fait aucune différence si j'ajoute l'autorisation d'accéder au dossier qui contient mon assemblage:
string folderOfT = Path.GetFullPath(Path.Combine(typeof(T).Assembly.Location, ".."));
permSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read, folderOfT));
// Same exception still occurs
Je peux « régler » le problème en utilisant une valeur différente pour AppDomainSetup.ApplicationBase
:
string loc = Path.GetFullPath(Assembly.GetExecutingAssembly().Location + @"\..");
Cela élimine l'exception, mais je ne peux pas utiliser cette "solution" car le but de l'AppDomain est de charger un assembly non approuvé à partir d'un dossier différent du dossier qui contient mon propre assembly. Par conséquent, loc
doit être le dossier qui contient l'assembly non approuvé, pas celui qui contient mon assembly.
(i) Je n'essaie pas de faire de réflexion, (ii) ReflectionPermission accorde l'accès pour accéder à des membres privés de tout type accessible; IL EST AFIN qu'il n'est pas nécessaire d'avoir accès aux membres du public. Je ne veux pas accorder ReflectionPermission car cela pourrait ouvrir des failles de sécurité. – Qwertie
(i) comme vous l'avez vu, ce n'est pas forcément votre code mais l'infrastructure qui doit le faire (c'est pourquoi rendre le type public résolu ce problème) ii) assez juste et vous avez contourné ce problème de toute façon –
le dossier "plug in" un sous-dossier de l'appbase existant? alors vous n'avez pas besoin de changer l'appbase de votre domaine d'application et l'assembly sera chargé correctement. Vous pouvez toujours contraindre le fichier IO dans le répertoire plug-in via une FileIOPermission –