views:

3261

answers:

2

I develop a critical application used by a multi-national company. Users in offices all around the globe need to be able to install this application.

The application is actually a plugin to Excel and we have an automatic installer based on Setuptools' easy_install that ensures that all a project's dependancies are automatically installed or updated any time a user switches on their Excel. It all works very elegantly as users are seldom aware of all the installation which occurs entirely in the background.

Unfortunately we are expanding and opening new offices which all have different proxy settings. These settings seem to change from day to day so we cannot keep up with the outsourced security guys who change stuff without telling us. It sucks but we just have to work around it.

I want to programatically detect the system-wide proxy settings on the Windows workstations our users run:

Everybody in the organisazation runs Windows XP and Internet Explorer. I've verified that everybody can download our stuff from IE without problems regardless of where they are int the world.

So all I need to do is detect what proxy settings IE is using and make Setuptools use those settings. Theoretically all of this information should be in the Registry.. but is there a better way to find it that is guaranteed not to change with people upgrade IE? For example is there a Windows API call I can use to discover the proxy settings?

In summary:

  • We use Python 2.4.4 on Windows XP
  • We need to detect the Internet Explorer proxy settings (e.g. host, port and Proxy type)
  • I'm going to use this information to dynamically re-configure easy_install so that it can download the egg files via the proxy.

UPDATE0:

I forgot one important detail: Each site has an auto-config "pac" file.

There's a key in Windows\CurrentVersion\InternetSettings\AutoConfigURL which points to a HTTP document on a local server which contains what looks like a javascript file.

The pac script is basically a series of nested if-statements which compare URLs against a regexp and then eventually return the hostname of the chosen proxy-server. The script is a single javascript function called FindProxyForURL(url, host)

The challenge is therefore to find out for any given server which proxy to use. The only 100% guaranteed way to do this is to look up the pac file and call the Javascript function from Python.

Any suggestions? Is there a more elegant way to do this?

+2  A: 

As far as I know, In a Windows environment, if no proxy environment variables are set, proxy settings are obtained from the registry's Internet Settings section. . Isn't it enough?

Or u can get something useful info from registry: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyServer

Edit:
sorry for don't know how to format comment's source code, I repost it here.

>>> 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
sunqiang
Are you sure? I have "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings" but it does not contain an object called ProxyServer.
Salim Fadhley
I just added an update introducing a load more complexity.
Salim Fadhley
Salim, I think maybe it's a JavaScript Parser Problem now? I have barely any experience with JavaScript. Some body just told me Microsoft's scriptcontrol maybe useful: ...don't know how to format source code here, I re post the demo code to the answer part.
sunqiang
Yes, this is the solution! I can execute the Pac file via win32com and discover the correct proxy to use. Nice one.
Salim Fadhley
+2  A: 

Here's a sample that should create a bullet green (proxy enable) or red (proxy disable) in your systray

It shows how to read and write in windows registry

it uses 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()
rapdum
Nice solution, but please check the update. By the way, this has to run headless behind Excel so we cannot use GTK.
Salim Fadhley