Friday, April 17, 2009

Use Python for Microsoft Windows Login and Group Policy Scripts

Background

Microsoft's Active Directory provides a way to distribute msi files and execute scripts on login, logout, shutdown etc. This makes it very easy to distribute a script to be run on login for a group of machines registered to Active Directory.

The type of scripts that can be run are .bat files, JScript or VBScript files via Windows Script Host (WSH. It's executables are wscript.exe (windows version) and cscript.exe (command-line version)), or windows executables (exe files). While those options are not too bad, I much prefer python for programming so here we are going to outline how to use python for these scripts.

Tim Golden has written some excellent wrapper code for python to make programming for Active Directory, WMI, shell work (like creating shortcuts) amoung other windows-specific things a pleasure.

Instructions
  • Get the Python MSI from Active State. We could have used the msi from python.org but we would have had installed the windows specific stuff that Mark Hammond wrote (pywin32 Windows Python Extensions) separately. And since I want to distribute this with Actirve Directory I would have had to convert the pywin32 package to an MSI as it is distributed as an exe. I tried compiling the source distribution to an msi with distutils (i.e.,
    python setup.py bdist_msi
    ) but the build failed because I did not have Visual Studio 2003 installed (I was building python 2.5). I do not want to buy or install Visual Studio (especially the old 2003 version) so I was happy that Active State packaged it all up in an msi already and distributed it for free! Thank you Active State!
  • If you would like to install Tim Golden's wrapper code via Active Directory as well (highly recommended) it is easy since he provided the setup.py distutils scripts for each package. Just download the zip files you want from his site and then for each one run
    python setup.py bdist_msi
    and an msi will be created for you. Thank you Tim!
  • You can distribute any python code that you want via Active Directory this way. Just make an msi of your code by writing a setup.py script and then running
    python setup.py bdist_msi
    . Distutils makes it easy!
  • Then, distribute those msi files with Active Directory Group Policy. I'll leave that to an exercise for the reader, but here is a good starting point. For some reason, I had to reboot a couple of times on some workstations for them to get the msi files installed.
  • Now your setup work is done and your workstations (or servers) have python installed along with pywin32 and optionally some nice wrapper code. From here you can write python scripts for those hosts that will be able to interact with active directory, WMI, COM, etc.
  • Now write your python login scripts.
  • To setup your login scripts to run at login you have a choice. First, you could compile your python code into exe files. You can do that without a lot of effort using py2exe (a distutils extension). This route adds a separate step (conversion to exe file) and every time you make a new exe it copies the whole python interpreter and other code with it so the exe files are large. This is a good option if you don't want to install python on the hosts though.
  • Windows Script Host (WSH) integration is another good option (I won't go into calling the python intepreter on your scripts via a bat file, but that is also an option). This way cscript.exe or wscript.exe runs the python intepreter which runs your script. Here's what you need to do to set this up.
    • First, run C:\Python25\Lib\site-packages\win32comext\axscript\client\pyscript.py (adjust for your installed version of python) on each host. This registers python as a language that Windows Script Host can run (called pyscript). Once this is done your python files (saved with the .pys extension can be used as Windows login scripts! You could put this command in a MSI file and distribute it with python so that when your login script runs it will already have been done.

    • There is one registry entry that needs to be added I have found in experimenting and below is some jscript code that does it (put it in a file in with a .js extension that you can publish it via a Group Policy in the Computer section of the policy to run on startup of the machine (best not done on logon to make sure it get's done before your python scripts run))


      var objShell = WScript.CreateObject("WScript.Shell");
      objShell.RegWrite("HKEY_CLASSES_ROOT\\pysFile\\shell\\open\\command\\", "\"C:\\WINDOWS\\system32\\wscript.exe\" \"%1\"", "REG_SZ");



    • Lastly setup your new shiny .pys script to run at login user the User side of the Active Directory Group Policy Object. Here is a site that shows you how.

    • This site has a lot of good information as well, but I have found that you don't need to do all the steps it outlines because the msi files above do most of it. The steps above worked for me.

0 comments: