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

У меня есть некоторый библиотечный код, который используется из моего приложения, а также используется настраиваемым действием .NET в проекте установщика Visual Studio. Код библиотеки, в свою очередь, использует блок ведения журнала Enterprise Library для ведения журнала. Как я могу получить информацию о конфигурации в 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] вместе со сборкой пользовательского действия), а динамически загруженные сборки, вызванные в файле конфигурации, - нет. Не вижу никакого способа обойти это.

5 ОТВЕТОВ

Не уверен, что это поможет, но вы можете записать в журнал 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

0
12.12.2008 06:17:35
Да, спасибо, но не совсем то, что я после. Я использую библиотечный код, который использует библиотеку предприятия. На самом деле мне не нужно нигде регистрироваться, просто глубоко вложенный код, использующий entlib, пытается инициализировать себя из конфигурации.
jlew 24.02.2009 18:13:13

У меня была похожая проблема с 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 до того, как он запустит настраиваемые действия, по умолчанию запускаются настраиваемые действия.

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

0
7.12.2011 03:49:40

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

1
26.02.2009 12:05:31
Не представляется возможным с корпоративной библиотекой.
jlew 26.02.2009 20:50:19

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

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

1
3.03.2009 00:13:24

Это может помочь людям, все еще имеющим дело с установщиками 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 Docs о реализации этого обработчика .

0
26.02.2018 21:01:07