Pergunta

Eu estou tentando usar um recurso da biblioteca Microsoft WinHttp que foi exposta pelos desenvolvedores do win32com. Infelizmente a maioria da biblioteca não parece ser documentado e não há exemplo da maneira correta de usar o win32inet apresenta através da biblioteca win32com.

Isto é o que eu tenho até agora:

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

Como você pode ver, tudo o que eu estou tentando fazer é usar o recurso win32inet para descobrir qual o proxy é o mais adequado para uso por um determinado URL, int seu caso foo.com.

Você pode me ajudar corrigir a sintaxe da última linha? MSN tem algum documentação bom para a função de ser envolvido mas os argumentos não parecem mapear o às da biblioteca python perfeitamente.

A versão fixa desse script deve:

  • Ser capaz de olhar-se que proxy para uso para qualquer URL.

  • Deve sempre exatamente o Internet Explorer faria (ou seja, usar o mesmo proxy)

  • Ele deve ser válido em qualquer válido set-up Windows XP. Isso significa que ele deve trabalhar com um proxy configurado explicitamente e também nenhum proxy em tudo.

  • Ele só precisa trabalhar em 32 bits do Windows XP com Python 2.4.4. Ele pode usar qualquer versão oficial lançada do win32com.

Eu estou usando Python2.4.4 com win32com no Windows XP.

Atualização de 0:

OU ... você pode me dar uma implementação alternativa em ctypes? Contanto que eu posso fazê-lo funcionar Eu estou feliz!

Foi útil?

Solução

Aqui está o código que cria sessão HINTERNET e usos que para obter detalhes de proxy, usando ctypes para acessar diretamente winhttp DLL. Ele funciona sem qualquer erro, mas não tenho set proxy na minha máquina, você pode ter de ajustar algumas constantes para obtê-lo direito. Vá através dos links do MSDN em código, de onde eu vi a 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

Outras dicas

A menos que haja uma forte razão para usar win32inet (que é confuso nesta área devido a limitações de SWIG), eu recomendo que você use ctypes vez.

Pelo menos com Python 2.7.6 e Pywin 218 no Windows XP x86 e Windows 8 x64, ele 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 a pena mencionar que o exemplo usa o WINHTTP_AUTOPROXY_CONFIG_URL opção autoproxy a fim de passar em uma URL explícita. Você pode usar outras opções, por exemplo, se você quiser detectar automaticamente usando DNS ou DHCP você pode fazer:

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

Você pode encontrar outras opções da ligação mostrou acima (no código)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top