2015-02-11 4 views
1

Я пытаюсь создать приложение песочницы для Windows, опираясь на «Как» найти здесь: «https://msdn.microsoft.com/en-us/library/bb763046(v=vs.110).aspx»C# AppDomain: Выполнить сборку из точки входа

В примере он загружает определенный тип из библиотеки DLL, тогда как Я хотел бы иметь возможность выполнить сборку из своей точки входа с ограниченными разрешениями.

Программа, которую я использую для целей тестирования, представляет собой простое приветственное приложение мира.

using System; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Console.WriteLine("Hello World!"); 
      Console.Read(); 
     } 
    } 
} 

Я пробовал два разных метода, чтобы попытаться достичь этого.

Метод 1.

Используйте метод «MethodInfo.Invoke» на точку входа сборки.

MethodInfo target = Assembly.Load(assemblyName).EntryPoint; 
target.Invoke(null, parameters); 

Это создает исключение доступа к методу из-за того, что основной метод является непубличным. Простым способом этого было бы сделать основной метод общедоступным, но у меня не будет такого доступа к сборкам, которые предназначены для использования с этим приложением.

Способ 2.

Используйте метод "AppDomain.ExecuteAssembly", как показано ниже.

newDomain.ExecuteAssembly(filePath, parameters); 

Это требует, чтобы домен приложения имеет как File IO Разрешение и UI Разрешение на монтаж должна быть выполнена, но я хочу, чтобы иметь возможность ограничить сборку от наличия этих разрешений.

Есть ли способ выполнить сборку из точки входа в домене с ограниченным доступом?

EDIT: Расположение сборки предоставляется из диалогового окна «Открыть файл» и затем передается следующему методу.

public int RunAssembly(string filePath, string[] parameters) 
{ 
    AppDomainSetup adSetup = new AppDomainSetup(); 
    adSetup.ApplicationBase = Path.GetDirectoryName(filePath); 

    PermissionSet permSet = new PermissionSet(PermissionState.None); 
    permSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution)); 

    StrongName fullTrustAssembly = typeof(Sandboxer).Assembly.Evidence.GetHostEvidence<StrongName>(); 

    newDomain = AppDomain.CreateDomain("Sandbox", null, adSetup, permSet, fullTrustAssembly); 

    return newDomain.ExecuteAssembly(filePath, parameters); 
} 

Как вы можете видеть единственное разрешение, с которым я хотел бы предоставить новый домен приложения, - это возможность запуска. Принимая во внимание, что для правильной работы ExecuteAssembly необходимы права доступа к файлу IO и UI.

+0

Пожалуйста, разместите код для вашего загрузчика. Метод № 1 отлично работает с обычным апдоменом. – Jester

+0

Из любопытства вы начали играть с Code Access Security после прочтения недавней публикации на форуме модников?(Я не вижу вопросов по этой теме слишком часто, и я просто сделал большой пост об этом на этом сайте день или два назад) –

+0

Я добавил код загрузки для метода № 2. Шут: Что вы подразумеваете под «нормальным» апдоменом? Скотт: Нет, я выбрал это из-за необходимости в рамках университетского проекта. – Phil

ответ

0

Использование метода # 1 и добавление разрешения отражения RestrictedMemberAccess, с тем чтобы непубличные члены могли быть вызваны, - это способ вызова сборки с полностью ограниченными разрешениями.

MethodInfo target = Assembly.Load(assemblyName).EntryPoint; 
(new ReflectionPermission(ReflectionPermissionFlag.RestrictedMemberAccess)).Assert(); 
target.Invoke(null, parameters); 

Полный код загрузки:

public int RunAssembly(string filePath, Object[] parameters) 
{ 
    AppDomainSetup adSetup = new AppDomainSetup(); 
    adSetup.ApplicationBase = Path.GetDirectoryName(filePath); 

    PermissionSet permSet = new PermissionSet(PermissionState.None); 
    permSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution)); 

    StrongName fullTrustAssembly = typeof(Sandboxer).Assembly.Evidence.GetHostEvidence<StrongName>(); 

    newDomain = AppDomain.CreateDomain("Sandbox", null, adSetup, permSet, fullTrustAssembly); 

    ObjectHandle handle = Activator.CreateInstanceFrom(
     _newDomain, typeof(Sandboxer).Assembly.ManifestModule.FullyQualifiedName, 
     typeof(Sandboxer).FullName 
     ); 

    newDomainInstance = (Sandboxer)handle.Unwrap(); 

    string assemblyName = Path.GetFileNameWithoutExtension(filePath); 

    return newDomainInstance.ExecuteAssembly(assemblyName, parameters); 
} 

public int ExecuteAssembly(string assemblyName, Object[] parameters) 
{ 
    MethodInfo target = Assembly.Load(assemblyName).EntryPoint; 
    (new ReflectionPermission(ReflectionPermissionFlag.RestrictedMemberAccess)).Assert(); 

    return target.Invoke(null, parameters); 
} 

Извините за имя неоднозначного метода, они должны быть изменены, если она будет использоваться.

1

Вы писали: «Это создает исключение доступа к методу из-за того, что основной метод не является общедоступным». Да, вы не должны вызывать метод, который не предназначен для вызова извне. Вы пытаетесь «переопределить» уровень защиты: я надеюсь, что это невозможно, так как это означает большое отверстие в системе.

+0

Да, я понимаю, почему точка входа сборки не должна быть общедоступной, поскольку она не предназначена для вызова из ничего, кроме CLR. Это оставляет вопрос о том, что является лучшим методом для программного вызова сборки с ограниченным набором конкретных разрешений, например. набор разрешений, который присутствует в первом редактировании. – Phil