如何为自动C ++ / CLI应用程序域指定ASP.NET探测路径?

时间:2015-06-08 14:45:22

标签: asp.net .net c++-cli

我有一个需要在ASP.NET WebApi操作的上下文中运行的C ++ / CLI DLL。

操作受ActionFilter影响,该操作使用log4net的LogicalThreadContext来设置包含请求ID的属性;这很好地将请求ID写入日志条目。

问题是,当从C ++ / CLI dll加载类时,ASP.NET似乎正在创建一个appdomain。 (我似乎无法找到有关其工作方式的任何文档;我很乐意找到一些。)当appdomain管道尝试反序列化所有内容时,它会因为无法找到log4net.dll而窒息(见下面的堆栈跟踪)。

Fusion日志显示它正在查看C:\Windows\System32\inetsrv,这是不正确的......我希望它可以查看探测路径或%PATH%环境变量。

一些数据点:

  • log4net.dll在网络应用的bin目录中提供,适用于我使用它的所有其他内容。
  • C ++ / CLI代码与log4net无依赖关系。
  • 如果我评论我对log4net.LogicalThreadContext.Properties[...]的来电,一切正常。
  • 如果我将log4net.dll从我的bin文件夹复制到C:\Windows\system32\inetsrv,一切正常。
  • web.config文件使用<probing privatePath="bin"/>元素指定探测路径。
  • Application_Start中的global.asax.cs方法将网络应用的bin目录添加到%PATH%环境变量:

        var currentPathEnvVar = Environment.GetEnvironmentVariable("PATH");
        var binPath = Path.Combine(Server.MapPath("~") ?? String.Empty, "bin");
        _log.DebugFormat("Prepending paths to PATH: [{0}]", binPath);
        Environment.SetEnvironmentVariable("PATH", String.Concat(binPath, Path.PathSeparator, currentPathEnvVar));
    
  • 日志显示%PATH%正在获得正确的前缀:

    2015-06-05 17:07:48,816 1   DEBUG   MyNamespace.WebApiApplication   (null)  Prepending paths to PATH: [C:\Program Files\MyCompany\MyApp\web\bin]
    

那么如何获得ASP.NET创建的appdomain以便在正确的位置查看加载程序集?

感谢。

这是所有这一切都失败时记录的堆栈跟踪。

2015-06-05 17:08:41,148 23  ERROR   MyNamespace.MyController    (null)  Controller action failed
System.TypeInitializationException: The type initializer for '<Module>' threw an exception. ---> <CrtImplementationDetails>.ModuleLoadException: The C++ module failed to load while attempting to initialize the default appdomain.
 ---> System.Runtime.Serialization.SerializationException: Unable to find assembly 'log4net, Version=1.2.13.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a'.

Server stack trace: 
   at System.Runtime.Serialization.Formatters.Binary.BinaryAssemblyInfo.GetAssembly()
   at System.Runtime.Serialization.Formatters.Binary.ObjectReader.GetType(BinaryAssemblyInfo assemblyInfo, String name)
   at System.Runtime.Serialization.Formatters.Binary.ObjectMap..ctor(String objectName, String[] memberNames, BinaryTypeEnum[] binaryTypeEnumA, Object[] typeInformationA, Int32[] memberAssemIds, ObjectReader objectReader, Int32 objectId, BinaryAssemblyInfo assemblyInfo, SizedArray assemIdToAssemblyTable)
   at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadObjectWithMapTyped(BinaryObjectWithMapTyped record)
   at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
   at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
   at System.Runtime.Remoting.Channels.CrossAppDomainSerializer.DeserializeObject(MemoryStream stm)
   at System.Runtime.Remoting.Messaging.SmuggledMethodCallMessage.FixupForNewAppDomain()
   at System.Runtime.Remoting.Channels.CrossAppDomainSink.DoDispatch(Byte[] reqStmBuff, SmuggledMethodCallMessage smuggledMcm, SmuggledMethodReturnMessage& smuggledMrm)
   at System.Runtime.Remoting.Channels.CrossAppDomainSink.DoTransitionDispatchCallback(Object[] args)

Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at System.AppDomain.IsDefaultAppDomain()
   at <CrtImplementationDetails>.GetDefaultDomain() in f:\dd\vctools\crt\crtw32\h\minternal.h:line 367
   at <CrtImplementationDetails>.DoCallBackInDefaultDomain(IntPtr function, Void* cookie) in f:\dd\vctools\crt\crtw32\h\minternal.h:line 401
   at <CrtImplementationDetails>.DefaultDomain.Initialize() in f:\dd\vctools\crt\crtw32\msilcrt\mstartup.cpp:line 278
   at <CrtImplementationDetails>.LanguageSupport.InitializeDefaultAppDomain(LanguageSupport* ) in f:\dd\vctools\crt\crtw32\msilcrt\mstartup.cpp:line 343
   at <CrtImplementationDetails>.LanguageSupport._Initialize(LanguageSupport* ) in f:\dd\vctools\crt\crtw32\msilcrt\mstartup.cpp:line 546
   at <CrtImplementationDetails>.LanguageSupport.Initialize(LanguageSupport* ) in f:\dd\vctools\crt\crtw32\msilcrt\mstartup.cpp:line 703
   --- End of inner exception stack trace ---
   at <CrtImplementationDetails>.ThrowModuleLoadException(String errorMessage, Exception innerException) in f:\dd\vctools\crt\crtw32\h\minternal.h:line 194
   at <CrtImplementationDetails>.LanguageSupport.Initialize(LanguageSupport* ) in f:\dd\vctools\crt\crtw32\msilcrt\mstartup.cpp:line 713
   at .cctor() in f:\dd\vctools\crt\crtw32\msilcrt\mstartup.cpp:line 754
   --- End of inner exception stack trace ---
   at MyNamespace.MyController.MyAction(String foo, Int64 bar, String baz)

1 个答案:

答案 0 :(得分:0)

这帮助我解决了类似的问题: https://blogs.msdn.microsoft.com/jorman/2007/08/31/loading-c-assemblies-in-asp-net/ 面对选项2.a和建议的解决方案效果很好:

  

受保护的无效Application_Start(对象发送者,EventArgs e){       字符串_path = String.Concat(System.Environment.GetEnvironmentVariable(“ PATH”),“;”,   System.AppDomain.CurrentDomain.RelativeSearchPath);       System.Environment.SetEnvironmentVariable(“ PATH”,_path,EnvironmentVariableTarget.Process); }