web-dev-qa-db-fra.com

La requête HttpClient lève une exception IOException

Le code suivant lève une IOException avec le message: "La clé de Registre spécifiée n'existe pas."

HttpClient client = new HttpClient();

Uri uri = new Uri("http://www.google.com");

client.GetAsync(uri);

C'est juste dans une application console dans Main. Il semble que l'erreur soit générée par mscorlib.dll! Microsoft.Win32.RegistryKey.Win32Error (int errorCode, string str). Je n'ai aucune idée pourquoi cette erreur est levée ou comment commencer à la déboguer.

Modifier la trace de la pile:

à Microsoft.Win32.RegistryKey.Win32Error (Int32 errorCode, String str)

C'est juste une ligne et il n'y a pas d'exception intérieure, etc.

La pile d'appels est:

mscorlib.dll!Microsoft.Win32.RegistryKey.Win32Error(int errorCode, string str) + 0x189 bytes    
mscorlib.dll!Microsoft.Win32.RegistryKey.GetValueKind(string name) + 0x7f bytes 
System.dll!System.Net.HybridWebProxyFinder.InitializeFallbackSettings() + 0x9e bytes    
[Native to Managed Transition]  
[Managed to Native Transition]  
System.dll!System.Net.AutoWebProxyScriptEngine.AutoWebProxyScriptEngine(System.Net.WebProxy proxy, bool useRegistry) + 0xd0 bytes   
System.dll!System.Net.WebProxy.UnsafeUpdateFromRegistry() + 0x2c bytes  
System.dll!System.Net.Configuration.DefaultProxySectionInternal.DefaultProxySectionInternal(System.Net.Configuration.DefaultProxySection section) + 0x1d8 bytes 
System.dll!System.Net.Configuration.DefaultProxySectionInternal.GetSection() + 0xec bytes   
System.dll!System.Net.WebRequest.InternalDefaultWebProxy.get() + 0xcc bytes 
System.dll!System.Net.HttpWebRequest.HttpWebRequest(System.Uri uri, System.Net.ServicePoint servicePoint) + 0xdf bytes  
System.dll!System.Net.HttpWebRequest.HttpWebRequest(System.Uri uri, bool returnResponseOnFailureStatusCode, string connectionGroupName, System.Action<System.IO.Stream> resendRequestContent) + 0x2b bytes  
System.Net.Http.dll!System.Net.Http.HttpClientHandler.CreateAndPrepareWebRequest(System.Net.Http.HttpRequestMessage request) + 0x59 bytes   
System.Net.Http.dll!System.Net.Http.HttpClientHandler.SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) + 0xf4 bytes  
System.Net.Http.dll!System.Net.Http.HttpMessageInvoker.SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) + 0x4f bytes 
System.Net.Http.dll!System.Net.Http.HttpClient.SendAsync(System.Net.Http.HttpRequestMessage request, System.Net.Http.HttpCompletionOption completionOption, System.Threading.CancellationToken cancellationToken) + 0x13e bytes 
System.Net.Http.dll!System.Net.Http.HttpClient.GetAsync(System.Uri requestUri, System.Net.Http.HttpCompletionOption completionOption) + 0xc bytes   

ConsoleServiceTest.exe!ConsoleServiceTest.Program.Main(string[] args) Line 20 + 0x17 bytes  C#
    [Native to Managed Transition]  
    [Managed to Native Transition]  
    Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() + 0x5a bytes  
    mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0x285 bytes 
    mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0x9 bytes   
    mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x57 bytes    
    mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x51 bytes   
    [Native to Managed Transition]  
70
JFoulkes

Il semble que cela soit dû à une récente mise à jour de sécurité pour .NET Framework: MS12-074: Des vulnérabilités dans .NET Framework pourraient permettre l'exécution de code à distance: 13 novembre 2012 (KB 2745030)

Tout se résume au code suivant dans la résolution du proxy Web:

[RegistryPermission(SecurityAction.Assert, Read=@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework")]
private static void InitializeFallbackSettings()
{
    allowFallback = false;
    try
    {
        using (RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\.NETFramework"))
        {
            try
            {
                if (key.GetValueKind("LegacyWPADSupport") == RegistryValueKind.DWord)
                {
                    allowFallback = ((int) key.GetValue("LegacyWPADSupport")) == 1;
                }
            }
            catch (UnauthorizedAccessException)
            {
            }
            catch (IOException)
            {
            }
        }
    }
    catch (SecurityException)
    {
    }
    catch (ObjectDisposedException)
    {
    }
}

Comme vous pouvez le voir, il recherche une clé de registre spécifique mentionnée dans l'article de la base de connaissances. Vous devez également noter que l'exception est interceptée en interne, mais vous la voyez car vous avez activé les exceptions de première chance dans les options de débogage de Visual Studio.

Si vous ne souhaitez pas voir cette exception, vous devez ajouter la clé de registre spécifiée avec la valeur 0:

Registry location: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework  
DWORD (32-bit) Value name: LegacyWPADSupport
Value data: 0

et pour les processus 32 bits sur les machines 64 bits:

Registry location: HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework
DWORD (32-bit) Value name: LegacyWPADSupport
Value data: 0
84
ligaz

Je suis d'accord avec la réponse de Ligaz et j'ai enregistré un problème de connexion à propos de ce bogue: https://connect.Microsoft.com/VisualStudio/feedback/details/773666/webrequest-create-eats-an-ioexception- au premier appel # détails

Enregistrez les éléments suivants dans un fichier .reg et importez-les dans le Registre pour éviter que cette erreur ne se produise:

Windows Registry Editor Version 5.00

; The following value prevents an IOException from being thrown and caught
; by System.Net.HybridWebProxyFinder.InitializeFallbackSettings() (in System.dll)
; when WebRequest.Create is first called.  By default the "LegacyWPADSupport"
; value doesn't exist, and when InitializeFallbackSettings calls GetValueKind,
; an IOException is thrown.  This adds the value with its default of false to
; prevent the exception.
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework]
"LegacyWPADSupport"=dword:00000000

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework]
"LegacyWPADSupport"=dword:00000000
28
Bill Menees

Pour une raison quelconque, votre code HttpClient recherche des paramètres de proxy dans le registre et ne peut pas ouvrir la clé. Un coup d'œil dans le code montre qu'il tente d'ouvrir HKCU, puis d'accéder à l'une des clés suivantes dans l'ordre:

  1. "HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Connections"
  2. "HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Connections"
  3. "HKLM\\SOFTWARE\\Policies\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"

L'un de ces trois est potentiellement la clé à laquelle votre processus n'a pas accès, pourquoi je ne suis pas sûr. Une solution possible consiste à désactiver les paramètres de détection automatique du proxy.

Sinon, vous devrez déterminer exactement quelle clé il charge et nous le ferons en deux étapes.

  1. Activer la journalisation System.Net .
  2. Téléchargez et exécutez Procmon, en filtrant l'accès au registre pour votre application, comme ceci:
  1. Une fois ouvert, désactivez la capture si elle est activée (la loupe doit être barrée d'un X rouge).enter image description here
  2. Commencez à filtrer le nom de votre processus.enter image description here
  3. Désélectionner toutes les options sauf les entrées de registre

enter image description here

  1. Activer la capture (cliquez sur la loupe)
  2. Exécutez votre application
  3. Trouvez l'entrée incriminée dans le journal, double-cliquez pour voir quelle clé elle ouvrait

Une fois que vous avez déterminé la clé incriminée, vous pouvez déterminer pourquoi votre application n'y a pas accès. Peut-être, si le nom de votre application est une indication, le compte d'utilisateur sous lequel votre service s'exécute n'a pas accès à la clé de Registre.

10
user7116