Quelle est la bonne manière d’utiliser win32inet.WinHttpGetProxyForUrl

J’essaie d’utiliser une fonctionnalité de la bibliothèque Microsoft WinHttp qui a été exposée par les développeurs de Win32com. Malheureusement, la majeure partie de la bibliothèque ne semble pas être documentée et il n’existe aucun exemple de la manière correcte d’utiliser les fonctionnalités de win32inet via la bibliothèque win32com.

C’est ce que j’ai jusqu’à présent:

import win32inet hinternet = win32inet.InternetOpen("foo 1.0", 0, "", "", 0) # Does not work!!! proxy = win32inet.WinHttpGetProxyForUrl( hinternet, u"http://www.foo.com", 0 ) 

Comme vous pouvez le voir, tout ce que j’essaie de faire est d’utiliser la fonctionnalité win32inet pour savoir quel proxy est le plus approprié à utiliser pour une URL donnée, dans son cas foo.com.

Pouvez-vous m’aider à corriger la syntaxe de la dernière ligne? MSN possède une bonne documentation pour la fonction en cours d’encapsulation, mais les arguments ne semblent pas correspondre parfaitement à ceux de la bibliothèque python.

La version corrigée de ce script devrait:

  • Être capable de rechercher le proxy à utiliser pour une URL donnée.

  • Il devrait toujours faire exactement ce que ferait Internet Explorer (c.-à-d. Utiliser le même proxy)

  • Il doit être valide sur toute configuration Windows XP valide. Cela signifie qu’il devrait fonctionner avec un proxy configuré explicitement et pas de proxy du tout.

  • Il suffit de travailler sur Windows XP 32bit avec Python 2.4.4. Il peut utiliser n’importe quelle version officielle de win32com.

J’utilise Python2.4.4 avec Win32Com sur Windows XP.

MISE À JOUR 0:

OU … pouvez-vous me donner une implémentation alternative dans les cTypes? Tant que je peux le faire fonctionner, je suis heureux!

Voici le code qui crée la session HINTERNET et l’utilise pour obtenir les détails du proxy, en utilisant ctypes pour accéder directement à la DLL winhttp. Cela fonctionne sans aucune erreur mais je n’ai pas de proxy sur ma machine, vous devrez peut-être modifier quelques constantes pour bien faire les choses. Passez par les liens msdn dans le code, d’où j’ai vu l’API.

 import ctypes import ctypes.wintypes winHttp = ctypes.windll.LoadLibrary("Winhttp.dll") # http://msdn.microsoft.com/en-us/library/aa384098(VS.85).aspx # first get a handle to HTTP session WINHTTP_ACCESS_TYPE_DEFAULT_PROXY=0 WINHTTP_NO_PROXY_NAME=WINHTTP_NO_PROXY_BYPASS=0 WINHTTP_FLAG_ASYNC=0x10000000 HINTERNET = winHttp.WinHttpOpen("PyWin32", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, WINHTTP_FLAG_ASYNC) print HINTERNET # now get proxy using HTTP session # http://msdn.microsoft.com/en-us/library/aa384097(VS.85).aspx """ BOOL WinHttpGetProxyForUrl( __in HINTERNET hSession, __in LPCWSTR lpcwszUrl, __in WINHTTP_AUTOPROXY_OPTIONS *pAutoProxyOptions, __out WINHTTP_PROXY_INFO *pProxyInfo ); """ # create C structure for WINHTTP_AUTOPROXY_OPTIONS #http://msdn.microsoft.com/en-us/library/aa384123(VS.85).aspx """ typedef struct { DWORD dwFlags; DWORD dwAutoDetectFlags; LPCWSTR lpszAutoConfigUrl; LPVOID lpvReserved; DWORD dwReserved; BOOL fAutoLogonIfChallenged; } WINHTTP_AUTOPROXY_OPTIONS; """ class WINHTTP_AUTOPROXY_OPTIONS(ctypes.Structure): _fields_ = [("dwFlags", ctypes.wintypes.DWORD), ("dwAutoDetectFlags", ctypes.wintypes.DWORD), ("lpszAutoConfigUrl", ctypes.wintypes.LPCWSTR), ("lpvReserved", ctypes.c_void_p ), ("dwReserved", ctypes.wintypes.DWORD), ("fAutoLogonIfChallenged",ctypes.wintypes.BOOL),] WINHTTP_AUTOPROXY_AUTO_DETECT = 0x00000001; WINHTTP_AUTO_DETECT_TYPE_DHCP = 0x00000001; WINHTTP_AUTO_DETECT_TYPE_DNS_A = 0x00000002; options = WINHTTP_AUTOPROXY_OPTIONS() options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP|WINHTTP_AUTO_DETECT_TYPE_DNS_A options.lpszAutoConfigUrl = 0 options.fAutoLogonIfChallenged = False # create C structure for WINHTTP_AUTOPROXY_OPTIONS # http://msdn.microsoft.com/en-us/library/aa383912(VS.85).aspx """ struct WINHTTP_PROXY_INFO { DWORD dwAccessType; LPWSTR lpszProxy; LPWSTR lpszProxyBypass; }; """ class WINHTTP_PROXY_INFO(ctypes.Structure): _fields_ = [("dwAccessType", ctypes.wintypes.DWORD), ("lpszProxy", ctypes.wintypes.LPCWSTR), ("lpszProxyBypass", ctypes.wintypes.LPCWSTR),] info = WINHTTP_PROXY_INFO() ret = winHttp.WinHttpGetProxyForUrl(HINTERNET, "http://www.google.com", ctypes.pointer(options), ctypes.pointer(info) ) print "proxy success?",ret if not ret: # some error lets see what is that? import win32api import win32con errorCode = win32api.GetLastError() print "win32 Error:",errorCode s = "" print win32api.FormatMessage(errorCode) print info.dwAccessType, info.lpszProxy, info.lpszProxyBypass 

A moins qu’il y ait une forte raison d’utiliser win32inet (ce qui est win32inet dans cette zone en raison des limitations de SWIG ), je vous recommande d’utiliser plutôt ctypes .

Au moins avec Python 2.7.6 et Pywin 218 sous Windows XP x86 et Windows 8 x64, cela fonctionne:

 import win32inet # http://msdn.microsoft.com/en-us/library/windows/desktop/aa384098(v=vs.85).aspx hinternet = win32inet.WinHttpOpen("foo", 0, "", "", 0) # http://msdn.microsoft.com/en-us/library/windows/desktop/aa384123(v=vs.85).aspx autoproxy_options = (2, 0, u"http://your-proxy-script-path", None, 0, 1) # http://msdn.microsoft.com/en-us/library/windows/desktop/aa384097(v=vs.85).aspx proxy = win32inet.WinHttpGetProxyForUrl(hinternet, u"http://www.google.com", autoproxy_options) print proxy 

Il vaut la peine de mentionner que l’exemple utilise l’option autoproxy WINHTTP_AUTOPROXY_CONFIG_URL afin de transmettre une URL explicite. Vous pouvez utiliser d’autres options, par exemple, si vous souhaitez détecter automatiquement en utilisant DNS ou DHCP:

 autoproxy_options = (1, 1|2, u"", None, 0, 1) 

Vous pouvez trouver d’autres options dans le lien ci-dessus (dans le code)