COM Interop 経由で MS Access から呼び出されるカスタム .Net dll コンポーネントがあります。
MSACCESS.EXE は呼び出しプロセスであるため、既定では、MS Access がインストールされている場所で、アセンブリの .config ファイルと参照されているすべての ddl を見つけようとします。
配置上の懸念から、すべてのカスタム コードを MS Office フォルダー構造内からではなく、別の場所から実行する必要があります。
以下を使用して、アセンブリにその構成情報をカスタムの場所から強制的にロードさせることができました。
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", customPath);
typeof(ConfigurationManager)
.GetField("s_initState", BindingFlags.NonPublic |
BindingFlags.Static)
.SetValue(null, 0);
typeof(ConfigurationManager)
.GetField("s_configSystem", BindingFlags.NonPublic |
BindingFlags.Static)
.SetValue(null, null);
typeof(ConfigurationManager)
.Assembly.GetTypes()
.Where(x => x.FullName ==
"System.Configuration.ClientConfigPaths")
.First()
.GetField("s_current", BindingFlags.NonPublic |
BindingFlags.Static)
.SetValue(null, null);
これは問題なく機能しているようで、この時点ではロギング以外はすべて機能しているようです。いずれにせよ、log4net.dll ファイルは、MSACCESS.EXE が配置されているディレクトリ以外の場所からはロードされません。
app.config ファイル (log4net.dll は .Net コンポーネントと同じディレクトリにあります) に以下を追加しようとしましたが、無視されているようです。
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="c:\mycomponent" />
</assemblyBinding>
</runtime>
SysInternals procmon を使用して、コンポーネントが Access から呼び出されたときに dll が検出され、正常に配置されていることを確認しましたが、MS Access ディレクトリからロードしようとして失敗しました。
とにかく、必要な場所から log4net.dll を強制的にロードする方法はありますか?
log4net 内部デバッグ ログからの出力は次のとおりです。
log4net:ERROR Failed to parse config file. Is the <configSections> specified as: <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net, Version=1.2.11.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a" />
System.Configuration.ConfigurationErrorsException: An error occurred creating the configuration section handler for log4net: Could not load file or assembly 'log4net' or one of its dependencies. The system cannot find the file specified. (C:\mycomponent\alt.config line 4) ---> System.IO.FileNotFoundException: Could not load file or assembly 'log4net' or one of its dependencies. The system cannot find the file specified.
at System.Configuration.TypeUtil.GetTypeWithReflectionPermission(IInternalConfigHost host, String typeString, Boolean throwOnError)
at System.Configuration.RuntimeConfigurationRecord.RuntimeConfigurationFactory.Init(RuntimeConfigurationRecord configRecord, FactoryRecord factoryRecord)
at System.Configuration.RuntimeConfigurationRecord.RuntimeConfigurationFactory.InitWithRestrictedPermissions(RuntimeConfigurationRecord configRecord, FactoryRecord factoryRecord)
at System.Configuration.RuntimeConfigurationRecord.CreateSectionFactory(FactoryRecord factoryRecord)
at System.Configuration.BaseConfigurationRecord.FindAndEnsureFactoryRecord(String configKey, Boolean& isRootDeclaredHere)
--- End of inner exception stack trace ---
at System.Configuration.BaseConfigurationRecord.FindAndEnsureFactoryRecord(String configKey, Boolean& isRootDeclaredHere)
at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject)
at System.Configuration.BaseConfigurationRecord.GetSection(String configKey)
at System.Configuration.ClientConfigurationSystem.System.Configuration.Internal.IInternalConfigSystem.GetSection(String sectionName)
at System.Configuration.ConfigurationManager.GetSection(String sectionName)
at System.Configuration.ConfigurationSettings.GetConfig(String sectionName)