Как использовать ведение журнала корпоративной библиотеки в настраиваемом действии .NET

У меня есть код библиотеки, который используется в моем приложении, а также используется настраиваемым действием .NET в проекте установщика Visual Studio. Код библиотеки, в свою очередь, использует блок ведения журнала Enterprise Library для ведения журнала. Как я могу получить информацию о конфигурации в корпоративной библиотеке в контексте моего настраиваемого действия, выполняемого внутри msiexec? Можно ли запустить механизм конфигурации в коде, прежде чем я буду обращаться к EntLib?

Обновление: я создал хак, который, похоже, будет работать, но основан на установке закрытого статического поля с использованием отражения. Жаль, что EntLib так тесно связан с .NET ConfigurationManager.

var factory = new LogWriterFactory( new FakeConfigSource( "foo.config" ) );
var field = typeof ( Logger ).GetField( "factory", BindingFlags.Static | BindingFlags.NonPublic );
field.SetValue( null, factory );
Logger.Write( "Test" );

Обновление 2: хотя этот хак работает на тестовом стенде, при запуске в контексте msiexec загрузчик сборок не находит сборки, указанные в файле конфигурации. Fuslogvw указывает, что AppBase - это каталог Windows system32, что имеет некоторый смысл. Я не понимаю, почему зависимости манифеста сборки настраиваемого действия (которые находятся в каталоге [TargetDir] вместе со сборкой настраиваемого действия) обнаруживаются, а динамически загружаемые сборки, вызываемые в файле конфигурации, - нет. Не вижу другого пути.


person jlew    schedule 05.12.2008    source источник


Ответы (5)


Невозможно использовать стандартный способ app.config, потому что этот app.config - это файл msiexec.config, который вам нужно будет отредактировать перед выполнением вашего MSI. Я бы порекомендовал использовать собственный метод загрузки конфигурации, который считывается из пользовательского XML или значений в MSI.

person Robert MacLean    schedule 26.02.2009
comment
Невозможно с корпоративной библиотекой. - person jlew; 26.02.2009

Я считаю, что проблема в том, что ваша сборка настраиваемого действия загружается в LoadFrom context, поэтому зависимости его манифеста разрешаются относительно его кодовой базы.

Вы можете решить эту проблему, создав новый AppDomain. Это даст вам возможность сбросить базовый каталог, загрузить новый App.config файл и так далее. Для создания новый AppDomain, заполняя свойства AppDomainSetup для ApplicationBase, ConfigurationFile, и так далее.

person Jeffrey Hantin    schedule 03.03.2009

Не уверен, что это поможет, но вы можете записать в журнал msi из настраиваемого действия. (Пример VBScript ниже :)

Const msiMessageTypeInfo = &H04000000
Const msiMessageTypeFatalExit = &H00000000
Const msiMessageTypeError = &H01000000
Const msiMessageTypeWarning = &H02000000
Const msiMessageTypeUser = &H03000000 

Dim rec : Set rec = Session.Installer.CreateRecord(1)
rec.StringData(1) = "Your log message."

Session.Message msiMessageTypeInfo, rec

Дополнительная информация из MSDN: http://msdn.microsoft.com/en-us/library/aa371672.aspx

person w4g3n3r    schedule 12.12.2008
comment
Да, спасибо, но не совсем то, что мне нужно. Я использую библиотечный код, который использует корпоративную библиотеку. На самом деле мне не нужно никуда регистрироваться, просто глубоко вложенный код, использующий entlib, пытается инициализировать себя из config. - person jlew; 24.02.2009

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

string installDir = System.IO.Path.GetDirectoryName(
                System.Reflection.Assembly.GetExecutingAssembly().Location);
System.IO.File.Copy(
                System.IO.Path.Combine(installDir, "<Insert Assembly Name>.dll"),
                System.IO.Path.Combine(Environment.SystemDirectory, "<Insert Assembly Name>.dll"),
                true);

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

Я все еще ищу действительно изящное решение этой проблемы и обновлю этот ответ, когда найду его.

person John Hunter    schedule 24.02.2009

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

Вы делаете это, обрабатывая событие AppDomain.AssemblyResolve. Я сделал это с помощью метода Install моего класса установщика, например:

internal class MyInstaller : Installer
{
    public override void Install(IDictionary stateSaver)
    {
        base.Install(stateSaver);

        AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
        {
            // Resolve assemblies here, e.g.:
            return
                args.Name == "My.Assembly"
                ? Assembly.LoadFrom(this.Context.Parameters["TARGETDIR"] + "\\My.Assembly.dll")
                : null;
        };

        // Continue install...
    }
}

Я бы рекомендовал прочитать страницу Документы MS по реализации обработчик.

person Paul    schedule 26.02.2018