使用Python编程检测Windows XP的系统代理设置

5 投票
2 回答
17327 浏览
提问于 2025-04-15 12:36

我正在开发一个对一家跨国公司非常重要的应用程序。全球各地的用户都需要能够安装这个应用。

这个应用其实是一个Excel的插件,我们有一个自动安装程序,基于Setuptools的easy_install,确保每当用户打开Excel时,所有项目所需的依赖项都会自动安装或更新。这一切都非常顺利,用户几乎不会意识到所有的安装过程都是在后台进行的。

不过,最近我们在扩展业务,开设新办公室,而这些办公室的代理设置各不相同。这些设置似乎每天都在变化,所以我们无法跟上那些外包的安全人员,他们在没有通知我们的情况下就更改了设置。这确实很麻烦,但我们只能想办法解决。

我想要通过编程的方式检测用户在Windows工作站上的系统代理设置:

我们组织里的每个人都在使用Windows XP和Internet Explorer。我已经确认,无论他们身处何地,大家都可以顺利地从IE下载我们的东西。

所以我需要做的就是检测IE使用的代理设置,然后让Setuptools使用这些设置。理论上,这些信息应该在注册表中,但有没有更好的方法来找到这些信息,以确保在用户升级IE时不会改变?比如,有没有Windows API可以用来发现代理设置?

总结一下:

  • 我们在Windows XP上使用Python 2.4.4
  • 我们需要检测Internet Explorer的代理设置(例如,主机、端口和代理类型)
  • 我将利用这些信息动态重新配置easy_install,以便通过代理下载egg文件。

更新0:

我忘记提一个重要的细节:每个站点都有一个自动配置的“pac”文件。

在Windows\CurrentVersion\InternetSettings\AutoConfigURL中有一个键,指向本地服务器上的一个HTTP文档,里面看起来像是一个javascript文件。

这个pac脚本基本上是一系列嵌套的if语句,它会将URL与正则表达式进行比较,最终返回所选代理服务器的主机名。这个脚本是一个名为FindProxyForURL(url, host)的单一javascript函数。

因此,挑战在于找出对于任何给定的服务器应该使用哪个代理。唯一100%可靠的方法是查找pac文件,并从Python调用这个Javascript函数。

有什么建议吗?有没有更优雅的方法来实现这个?

2 个回答

4

这里有一个示例,可以在你的系统托盘中显示一个绿色的圆点(表示代理已启用)或红色的圆点(表示代理已禁用)。

这个示例展示了如何在Windows注册表中读取和写入数据。

它使用了gtk这个工具。

#!/usr/bin/env python
import gobject
import gtk
from _winreg import *

class ProxyNotifier:
    def __init__(self):        
        self.trayIcon = gtk.StatusIcon()
        self.updateIcon()

        #set callback on right click to on_right_click
        self.trayIcon.connect('popup-menu', self.on_right_click)
        gobject.timeout_add(1000, self.checkStatus)

    def isProxyEnabled(self):

        aReg = ConnectRegistry(None,HKEY_CURRENT_USER)

        aKey = OpenKey(aReg, r"Software\Microsoft\Windows\CurrentVersion\Internet Settings") 
        subCount, valueCount, lastModified = QueryInfoKey(aKey)

        for i in range(valueCount):                                           
            try:
                n,v,t = EnumValue(aKey,i)
                if n == 'ProxyEnable':
                    return v and True or False
            except EnvironmentError:                                               
                break
        CloseKey(aKey)  

    def invertProxyEnableState(self):
        aReg = ConnectRegistry(None,HKEY_CURRENT_USER)
        aKey = OpenKey(aReg, r"Software\Microsoft\Windows\CurrentVersion\Internet Settings", 0, KEY_WRITE)
        if self.isProxyEnabled() : 
            val = 0 
        else:
            val = 1
        try:   
            SetValueEx(aKey,"ProxyEnable",0, REG_DWORD, val) 
        except EnvironmentError:                                          
            print "Encountered problems writing into the Registry..."
        CloseKey(aKey)

    def updateIcon(self):
        if self.isProxyEnabled():
            icon=gtk.STOCK_YES
        else:
            icon=gtk.STOCK_NO
        self.trayIcon.set_from_stock(icon)

    def checkStatus(self):
        self.updateIcon()
        return True


    def on_right_click(self, data, event_button, event_time):
        self.invertProxyEnableState()
        self.updateIcon()


if __name__ == '__main__':
    proxyNotifier = ProxyNotifier()
    gtk.main()
3

据我所知,在Windows环境下,如果没有设置代理的环境变量,代理设置会从注册表的互联网设置部分获取。
这样就够了吗?

或者你可以从注册表中获取一些有用的信息:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyServer

补充:
抱歉我不知道怎么格式化评论中的源代码,所以我在这里重新发了一遍。

>>> import win32com.client
>>> js = win32com.client.Dispatch('MSScriptControl.ScriptControl')
>>> js.Language = 'JavaScript'
>>> js.AddCode('function add(a, b) {return a+b;}')
>>> js.Run('add', 1, 2)
3

撰写回答