如何为自动C+;指定ASP.NET探测路径+/CLI应用程序域?
我有一个C++/CLI DLL,需要在ASP.NET WebApi操作的上下文中运行 该操作受ActionFilter的影响,ActionFilter使用log4net的如何为自动C+;指定ASP.NET探测路径+/CLI应用程序域?,asp.net,.net,c++-cli,Asp.net,.net,C++ Cli,我有一个C++/CLI DLL,需要在ASP.NET WebApi操作的上下文中运行 该操作受ActionFilter的影响,ActionFilter使用log4net的LogicalThreadContext设置包含请求ID的属性;这可以很好地将请求ID写入日志条目 问题是,当从C++/CLI dll加载类时,ASP.NET似乎正在创建appdomain。(我似乎找不到任何关于如何工作的文档;我很想找到一些。)当appdomain管道尝试反序列化所有内容时,它会阻塞,因为它找不到log4net
LogicalThreadContext
设置包含请求ID的属性;这可以很好地将请求ID写入日志条目
问题是,当从C++/CLI dll加载类时,ASP.NET似乎正在创建appdomain。(我似乎找不到任何关于如何工作的文档;我很想找到一些。)当appdomain管道尝试反序列化所有内容时,它会阻塞,因为它找不到log4net.dll(请参见下面的堆栈跟踪)
Fusion日志显示它正在查看C:\Windows\System32\inetsrv
,这是不正确的。。。我希望它在探测路径中或沿着%path%
环境变量查找
几个数据点:
- log4net.dll可以在web应用程序的
目录中找到,并且可以很好地用于我使用它的所有其他用途bin
- C++/CLI代码对log4net没有依赖关系
- 如果我注释掉对
的调用,一切都会正常工作log4net.LogicalThreadContext.Properties[…]
- 如果我将log4net.dll从
文件夹复制到bin
,一切正常C:\Windows\system32\inetsrv
- web.config文件使用
元素指定探测路径
中的Myglobal.asax.cs
方法将web应用程序的Application\u Start
目录前置到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]
这是所有这些发生时记录的堆栈跟踪
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)
2015-06-05 17:08:41148 23错误MyNamespace.MyController(null)控制器操作失败
System.TypeInitializationException:“”的类型初始值设定项引发异常。-->。模块化:C++模块在初始化默认AppDe域时加载失败。
--->System.Runtime.Serialization.SerializationException:找不到程序集“log4net,版本=1.2.13.0,区域性=中性,PublicKeyToken=669e0ddf0bb1aa2a”。
服务器堆栈跟踪:
在System.Runtime.Serialization.Formatters.Binary.BinarySassemblyInfo.GetAssembly()中
在System.Runtime.Serialization.Formatters.Binary.ObjectReader.GetType(BinaryAssemblyInfo assemblyInfo,字符串名称)
在System.Runtime.Serialization.Formatters.Binary.ObjectMap..ctor(String objectName,String[]MemberName,BinaryTypeEnum[]binaryTypeEnumA,Object[]TypeInformation,Int32[]MemberAssemblyMids,ObjectReader ObjectReader,Int32 objectId,BinaryAssemblyInfo assemblyInfo,SizeArray AssemblyTable)
在System.Runtime.Serialization.Formatters.Binary.\u BinaryParser.ReadObjectWithMapTyped(BinaryObjectWithMapTyped记录)
在System.Runtime.Serialization.Formatters.Binary.\uuu BinaryParser.Run()中
在System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler处理程序、\uu BinaryParser serParser、Boolean fCheck、Boolean isCrossAppDomain、IMethodCallMessage方法CallMessage)
在System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(流序列化流、HeaderHandler处理程序、布尔fCheck、布尔isCrossAppDomain、IMethodCallMessage方法CallMessage)
在System.Runtime.Remoting.Channel.CrossAppDomainSerializer.DeserializeObject(MemoryStream stm)中
在System.Runtime.Remoting.Messaging.SnockedMethodCallMessage.FixupForNewAppDomain()中
在System.Runtime.Remoting.Channels.CrossAppDomainSink.DoDispatch(字节[]reqStmBuff,走私方法CallMessage走私DMCM,走私方法ReturnMessage&走私DMRM)
在System.Runtime.Remoting.Channels.CrossAppDomainSink.DotTransitionDispatchCallback(对象[]参数)处
在[0]处重试异常:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg,IMessage retMsg)
at System.Runtime.Remoting.proxy.RealProxy.PrivateInvoke(MessageData&msgData,Int32类型)
位于System.AppDomain.IsDefaultAppDomain()处
在f:\dd\vctools\crt\crtw32\h\minternal.h中的.GetDefaultDomain()处:第367行
f:\dd\vctools\crt\crtw32\h\minternal.h中的.DoCallBackInDefaultDomain(IntPtr函数,Void*cookie):第401行
在f:\dd\vctools\crt\crtw32\msilcrt\mstartup.cpp中的.DefaultDomain.Initialize()处:第278行
在f:\dd\vctools\crt\crtw32\msilcrt\mstartup.cpp中的at.LanguageSupport.InitializedDefaultAppDomain(LanguageSupport*):第343行
at.LanguageSupport.\u在f:\dd\vctools\crt\crtw32\msilcrt\mstartup.cpp中初始化(LanguageSupport*):第546行
f:\dd\vctools\crt\crtw32\msilcrt\mstartup.cpp中的at.LanguageSupport.Initialize(LanguageSupport*):第703行
---内部异常堆栈跟踪的结束---
f:\dd\vctools\crt\crtw32\h\minternal.h中的.ThrowModuleLoadException(字符串errorMessage,Exception innerException):第194行
f:\dd\vctools\crt\crtw32\msilcrt\mstartup.cpp中的at.LanguageSupport.Initialize(LanguageSupport*):第713行
在f:\dd\vctools\crt\crtw32\msilcrt\mstartup.cpp中的.cctor()处:第754行
---内部异常堆栈跟踪的结束---
在MyNamespace.MyController.MyAction(字符串foo、Int64 bar、字符串baz)
这帮助我解决了类似的问题:
面对选项2.a和提议的解决方案效果良好:
受保护的无效应用程序\u启动(对象发送方,事件参数e){
String _path=String.Concat(System.Environment.GetEnvironmentVariable(“path”),“;”,
System.AppDomain.CurrentDomain.RelativeSearchPath);
System.Environment.SetEnvironmentVariable(“PATH”,_PATH,EnvironmentVariableTarget.Process);}