Se produce una excepción System.Security.SecurityException cuando se usa la clase System.Net.HttpWebRequest desde una aplicación de Windows Forms basada en .NET Framework 2.0 o 3.5 SP1
Este artículo le ayuda a resolver lo que se produce al usar la clase desde una aplicación de Windows Forms basada en System.Security.SecurityException System.Net.HttpWebRequest Microsoft .NET Framework 3.5 SP1.
Versión del producto original: Microsoft .NET Framework 3.5 Service Pack 1
Número KB original: 2512713
Síntomas
Está usando la clase desde una aplicación Windows Forms basada en System.Net.HttpWebRequest Microsoft .NET Framework 3.5 Service Pack 1 de forma sincrónica. En concreto, este código se ejecuta en el subproceso principal o de la interfaz de usuario. La aplicación Windows Forms genera una excepción intermitente de tipo System.Security.SecurityException que tiene un mensaje similar al siguiente:
Error al solicitar el permiso de tipo 'System.Security.Permissions.UIPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.
La excepción mostrará un callstack defectuoso similar al siguiente:
0:000> !clrstack
ESP EIP
<<ESP>> <<EIP>> System.Threading.WaitHandle.WaitOneNative(Microsoft.Win32.SafeHandles.SafeWaitHandle, UInt32, Boolean, Boolean)
<<ESP>> <<EIP>> System.Threading.WaitHandle.WaitOne(Int64, Boolean)
<<ESP>> <<EIP>> System.Threading.WaitHandle.WaitOne(Int32, Boolean)
<<ESP>> <<EIP>> System.Net.NetworkAddressChangePolled.CheckAndReset()
<<ESP>> <<EIP>> System.Net.NclUtilities.get_LocalAddresses()
<<ESP>> <<EIP>> System.Net.WebProxyScriptHelper.myIpAddress()
.........
.........
<<ESP>> <<EIP>> System.Net.WebProxyScriptHelper+MyMethodInfo.Invoke(System.Object, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo)
<<ESP>> <<EIP>> Microsoft.JScript.LateBinding.CallOneOfTheMembers(System.Reflection.MemberInfo[], System.Object[], Boolean, System.Object, System.Reflection.Binder, System.Globalization.CultureInfo, System.String[], Microsoft.JScript.Vsa.VsaEngine, Boolean ByRef)
<<ESP>> <<EIP>> Microsoft.JScript.LateBinding.Call(System.Reflection.Binder, System.Object[], System.Reflection.ParameterModifier[], System.Globalization.CultureInfo, System.String[], Boolean, Boolean, Microsoft.JScript.Vsa.VsaEngine)
<<ESP>> <<EIP>> Microsoft.JScript.LateBinding.Call(System.Object[], Boolean, Boolean, Microsoft.JScript.Vsa.VsaEngine).........
.........
<<ESP>> <<EIP>> Microsoft.JScript.JSMethodInfo.Invoke(System.Object, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo)
<<ESP>> <<EIP>> Microsoft.JScript.FunctionObject.Call(System.Object[], System.Object, Microsoft.JScript.ScriptObject, Microsoft.JScript.Closure, System.Reflection.Binder, System.Globalization.CultureInfo)
<<ESP>> <<EIP>> Microsoft.JScript.Closure.Call(System.Object[], System.Object, System.Reflection.Binder, System.Globalization.CultureInfo)
<<ESP>> <<EIP>> Microsoft.JScript.LateBinding.CallValue(System.Object, System.Object[], Boolean, Boolean, Microsoft.JScript.Vsa.VsaEngine, System.Object, System.Reflection.Binder, System.Globalization.CultureInfo, System.String[])
<<ESP>> <<EIP>> Microsoft.JScript.LateBinding.CallValue(System.Object, System.Object, System.Object[], Boolean, Boolean, Microsoft.JScript.Vsa.VsaEngine)
.........
.........
<<ESP>> <<EIP>> System.Reflection.MethodBase.Invoke(System.Object, System.Object[])
<<ESP>> <<EIP>> System.Net.VsaWebProxyScript.CallMethod(System.Object, System.String, System.Object[])
<<ESP>> <<EIP>> System.Net.VsaWebProxyScript.Run(System.String, System.String)
.........
.........
<<ESP>> <<EIP>> System.Net.IWebProxyScript.Run(System.String, System.String)
<<ESP>> <<EIP>> System.Net.AutoWebProxyScriptEngine.GetProxies(System.Uri, Boolean, System.Net.AutoWebProxyState ByRef, Int32 ByRef)
<<ESP>> <<EIP>> System.Net.WebProxy.GetProxiesAuto(System.Uri, System.Net.AutoWebProxyState ByRef, Int32 ByRef)
<<ESP>> <<EIP>> System.Net.ProxyScriptChain.GetNextProxy(System.Uri ByRef)
<<ESP>> <<EIP>> System.Net.ProxyChain+ProxyEnumerator.MoveNext()
<<ESP>> <<EIP>> System.Net.ServicePointManager.FindServicePoint(System.Uri, System.Net.IWebProxy, System.Net.ProxyChain ByRef, System.Net.HttpAbortDelegate ByRef, Int32 ByRef)
<<ESP>> <<EIP>> System.Net.HttpWebRequest.FindServicePoint(Boolean)
<<ESP>> <<EIP>> System.Net.HttpWebRequest.GetRequestStream(System.Net.TransportContext ByRef)
<<ESP>> <<EIP>> System.Net.HttpWebRequest.GetRequestStream().........
.........
<<ESP>> <<EIP>> YourApplicationFunction.....
.........
.........
Causa
Cuando la clase se ejecuta desde el subproceso principal, que también es el subproceso de interfaz de usuario (UI), es posible que deba ejecutar el protocolo WPAD (Detección automática de proxy web) para detectar si se necesita un proxy para llegar a la dirección URL de System.Net.HttpWebRequest destino. Durante este proceso, descarga y compila el script PAC (Configuración automática de proxy) en la memoria e intenta ejecutar la función según System.Net FindProxyForURL la especificación PAC.
Al hacerlo, crea un dominio de aplicación interno dentro de la aplicación que se ejecuta con permisos mínimos y, lo que es más importante, no concede el permiso de la interfaz de usuario a este System.Net nuevo dominio de aplicación. La evaluación de un proxy y la ejecución de la función JavaScript se produce en el contexto de este nuevo dominio de aplicación y durante este proceso puede que necesite ejecutar varias funciones auxiliares según la especificación PAC, como , , para calcular el FindProxyForURL System.Net isInNet dnsResolve myIpAddress proxy.
Por ejemplo, al ejecutar la función se intentará evaluar la dirección IP actual del equipo actual y, en algún momento, puede que tenga que myIpAddress usar la llamada de System.Net System.Threading.WaitHandle.WaitOne() función. Cuando se llama a esta función desde el subproceso principal o de la interfaz de usuario, esta llamada seguirá procesando mensajes de ventana System.Threading.WaitHandle.WaitOne() mientras está esperando.
Si el mensaje de ventana se procesa durante la llamada, .NET framework Common Language Runtime (CLR) realizará una comprobación de pila completa y exigirá el permiso de WaitOne() la interfaz de usuario. Si encuentra algún error de coincidencia en los permisos, se System.Security.SecurityException produce un.
Solución
Este comportamiento es una característica del diseño de la aplicación.
Para evitar este problema, puede cambiar al uso de la clase de forma asincrónica o seguir usando el enfoque sincrónico, pero ejecutarlo desde un subproceso en segundo plano o un subproceso que no sea de System.Net.HttpWebRequest interfaz de usuario. De este modo, el proceso de ventana tendrá un dominio libre del subproceso de interfaz de usuario sin tener que interrumpir las llamadas de espera en un dominio de aplicación diferente.
Otro enfoque que puede usar es mantener el mismo código que antes, pero en lugar de ejecutar la detección automática de proxy en el subproceso principal, puede crear un nuevo subproceso e intentar ejecutar la función en este subproceso en segundo plano y permitir que el subproceso en segundo plano realice la detección automática de System.Net System.Net.WebProxy.GetProxy proxy. Una vez que el subproceso en segundo plano recupera la dirección de un servidor proxy, puede establecer la propiedad del objeto y Proxy HttpWebRequest establecerla en un proxy fijo. Esto evitará la detección automática de proxy en el subproceso principal y no producirá la excepción.
Si el entorno tiene configurado un proxy fijo, puede desactivar completamente la detección automática de proxy agregando las siguientes opciones de configuración en el archivo de configuración de la aplicación:
<system.net>
<defaultProxy>
<proxy autoDetect="False" usesystemdefault="False" proxyaddress="http://yourProxy:yourProxyPort"/>
</defaultProxy>
</system.net>
Nota
Aunque la ejecución de solicitudes HTTP sincrónicas con la clase debe funcionar bien en la mayoría de los escenarios, no se recomienda ejecutar operaciones de red sincrónicas, como enviar solicitudes HTTP desde el subproceso principal o de la interfaz de usuario debido a posibles retrasos detectados durante las operaciones de red (como la dirección IP o la resolución DNS, la detección de System.Net.HttpWebRequest proxy, etc.). Es mejor ejecutar estas solicitudes sincrónicas desde un subproceso en segundo plano o ejecutar las solicitudes de forma asincrónica.