Quelle est la bonne façon d'utiliser win32inet.WinHttpGetProxyForUrl
Question
Je suis en train d'utiliser une fonctionnalité de la bibliothèque Microsoft WinHttp qui a été exposé par les développeurs de Win32com. Malheureusement, la plupart de la bibliothèque ne semble pas être documenté et il n'y a pas d'exemple de la bonne façon d'utiliser les fonctions de win32inet via la bibliothèque win32com.
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 je suis en train de faire est d'utiliser la fonction win32inet pour savoir quel proxy est appropriée à utiliser pour une URL donnée, int son cas foo.com.
Pouvez-vous me aider à corriger la syntaxe de la dernière ligne? MSN a une certaine une bonne documentation pour la fonction étant enveloppé mais les args ne semblent pas cartographier la à ceux de la bibliothèque python parfaitement.
La version fixe de ce script doit:
-
Être en mesure de rechercher quel proxy utiliser pour une URL donnée.
-
Il doit toujours faire exactement ce que Internet Explorer ferait (à savoir utiliser le même proxy)
-
Il doit être valide sur tout valide Windows XP mis en place. Cela signifie qu'il devrait fonctionner avec un proxy explicitement configuré et pas de proxy du tout.
-
Il n'a besoin que de travailler sur Windows XP 32 bits avec Python 2.4.4. Il peut utiliser une version officielle publiée de win32com.
J'utilise Python2.4.4 avec Win32Com sous Windows XP.
Mise à jour 0:
OU ... Pouvez-vous me donner une implémentation alternative ctypes? Tant que je peux le faire fonctionner, je suis heureux!
La solution
Voici le code qui crée session HINTERNET et utilise pour obtenir des détails proxy, en utilisant ctypes pour accéder directement DLL winhttp. Il fonctionne sans erreur, mais je n'ai pas de jeu de procuration sur ma machine, vous devrez peut-être modifier quelques constantes pour obtenir ce droit. Aller à travers les liens msdn dans le code, d'où je l'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
Autres conseils
À moins d'une raison forte pour l'utilisation win32inet
(qui est en désordre dans ce domaine en raison des limites de SWIG
), je vous recommande d'utiliser à la place ctypes
.
Au moins, avec et Python 2.7.6
sur x86 de Windows Pywin 218
XP et Windows 8 x64, il 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
intéressant de mentionner que l'exemple utilise l'option autoproxy WINHTTP_AUTOPROXY_CONFIG_URL afin de passer dans une URL explicite. Vous pouvez utiliser d'autres options, par exemple, si vous voulez détecter automatiquement en utilisant DNS ou DHCP que vous pouvez faire:
autoproxy_options = (1, 1|2, u"", None, 0, 1)
Vous pouvez trouver d'autres options dans le lien ci-dessus (dans montré le code)