¿Cuál es la forma correcta de utilizar win32inet.WinHttpGetProxyForUrl?
Pregunta
Estoy intentando utilizar una función de la biblioteca Microsoft WinHttp que ha sido expuesta por los desarrolladores de Win32com.Desafortunadamente, la mayor parte de la biblioteca no parece estar documentada y no hay ningún ejemplo de la forma correcta de utilizar las funciones de win32inet a través de la biblioteca win32com.
Esto es lo que tengo hasta ahora:
import win32inet
hinternet = win32inet.InternetOpen("foo 1.0", 0, "", "", 0)
# Does not work!!!
proxy = win32inet.WinHttpGetProxyForUrl( hinternet, u"http://www.foo.com", 0 )
Como puede ver, todo lo que intento hacer es usar la función win32inet para descubrir qué proxy es el apropiado para una URL determinada, en su caso foo.com.
¿Puedes ayudarme a corregir la sintaxis de la última línea?MSN tiene algunos buena documentación para la función que se está empaquetando pero los argumentos no parecen asignarse perfectamente a los de la biblioteca de Python.
La versión corregida de este script debería:
Poder buscar qué proxy usar para cualquier URL dada.
Siempre debería hacer exactamente lo que haría Internet Explorer (es decir,usar el mismo proxy)
Debería ser válido en cualquier configuración válida de Windows XP.Eso significa que debería funcionar con un proxy configurado explícitamente y tampoco con ningún proxy.
Sólo necesita funcionar en Windows XP de 32 bits con Python 2.4.4.Puede utilizar cualquier versión oficial de win32com.
Estoy usando Python2.4.4 con Win32Com en Windows XP.
ACTUALIZACIÓN 0:
O...¿Puedes darme una implementación alternativa en cTypes?¡Mientras pueda hacerlo funcionar, estoy feliz!
Solución
Este es el código que crea la sesión HINTERNET y la usa para obtener detalles del proxy, usando ctypes para acceder directamente a DLL winhttp. Funciona sin ningún error pero no tengo ningún conjunto proxy en mi máquina, es posible que tenga que ajustar algunas constantes para hacerlo bien. Ir a través de los enlaces de MSDN en código, desde donde he visto la 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
Otros consejos
A menos que haya una razón de peso para usar win32inet
(que es desordenado en esta área debido a las limitaciones de SWIG
), recomiendo que utilice ctypes
lugar.
al menos con Python 2.7.6
y Pywin 218
en Windows XP x86 y Windows 8 x64, funciona:
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
Vale la pena mencionar que el ejemplo utiliza la opción de proxy automático WINHTTP_AUTOPROXY_CONFIG_URL para pasar una URL explícita.Puedes usar otras opciones, por ejemplo, si quieres autodetectar usando DNS o DHCP puedes hacer:
autoproxy_options = (1, 1|2, u"", None, 0, 1)
Puede encontrar otras opciones en el enlace que se muestra arriba (en el código)