[Spambayes-checkins] spambayes/Outlook2000 addin.py,1.114,1.115

Mark Hammond mhammond at users.sourceforge.net
Sun Dec 7 19:55:45 EST 2003


Update of /cvsroot/spambayes/spambayes/Outlook2000
In directory sc8-pr-cvs1:/tmp/cvs-serv29168

Modified Files:
	addin.py 
Log Message:
A number of changes to better support us existing in the 'COM Addins'
list when running the binary version:
* By default, no longer register in both HKLM and HKCU - registering
  in both means we don't appear in the addins list.
* Support special registration command-line to register in HKLM instead
  of the default HKCU - see the comments on this
* Support the addin being selected and de-selected multiple times via
  the Outlook GUI.  This was mainly removing old object references when
  'Close' is called.
* When the user manually de-selects us via the 'Addins' list, we remove
  the SpamBayes toolbar.  TODO: somehow exploit this so that at uninstall 
  time we can also remove the toolbar.


Index: addin.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/Outlook2000/addin.py,v
retrieving revision 1.114
retrieving revision 1.115
diff -C2 -d -r1.114 -r1.115
*** addin.py	27 Oct 2003 03:36:24 -0000	1.114
--- addin.py	8 Dec 2003 00:55:43 -0000	1.115
***************
*** 3,6 ****
--- 3,7 ----
  import warnings
  import traceback
+ import _winreg
  
  # *sigh* - this is for the binary installer, and for the sake of one line
***************
*** 86,94 ****
  gencache.EnsureModule('{2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}', 0, 2, 1,
                          bForDemand=True, bValidateFile=bValidateGencache) # Office 9
  
- # Register what vtable based interfaces we need to implement.
- # Damn - we should use EnsureModule for the _IDTExtensibility2 typelib, but
- # win32all 155 and earlier don't like us pre-generating :(
- universal.RegisterInterfaces('{AC0714F2-3D04-11D1-AE7D-00A0C90F26F4}', 0, 1, 0, ["_IDTExtensibility2"])
  try:
      from win32com.client import CastTo, WithEvents
--- 87,97 ----
  gencache.EnsureModule('{2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}', 0, 2, 1,
                          bForDemand=True, bValidateFile=bValidateGencache) # Office 9
+ # We the "Addin Designer" typelib for its constants
+ gencache.EnsureModule('{AC0714F2-3D04-11D1-AE7D-00A0C90F26F4}', 0, 1, 0,
+                         bForDemand=True, bValidateFile=bValidateGencache)
+ # ... and also for its _IDTExtensibility2 vtable interface.
+ universal.RegisterInterfaces('{AC0714F2-3D04-11D1-AE7D-00A0C90F26F4}', 0, 1, 0,
+                              ["_IDTExtensibility2"])
  
  try:
      from win32com.client import CastTo, WithEvents
***************
*** 965,980 ****
                          # for not broken - can't find toolbar.  Create a new one.
                          # Create it as a permanent one (which is default)
-                         if self.explorers_collection.have_created_toolbar:
-                             # Eeek - we have already created a toolbar, but
-                             # now we can't find it.  It is likely this is the
-                             # first time we are being run, and outlook is
-                             # being started with multiple Windows open.
-                             # Hopefully things will get back to normal once
-                             # Outlook is restarted (which testing shows it does)
-                             return
- 
                          print "Creating new SpamBayes toolbar to host our buttons"
!                         self.toolbar = bars.Add(toolbar_name, constants.msoBarTop, Temporary=False)
!                         self.explorers_collection.have_created_toolbar = True
                      self.toolbar.Visible = True
                  parent = self.toolbar
--- 968,975 ----
                          # for not broken - can't find toolbar.  Create a new one.
                          # Create it as a permanent one (which is default)
                          print "Creating new SpamBayes toolbar to host our buttons"
!                         self.toolbar = bars.Add(toolbar_name,
!                                                 constants.msoBarTop,
!                                                 Temporary=False)
                      self.toolbar.Visible = True
                  parent = self.toolbar
***************
*** 1122,1129 ****
          self.manager = manager
          self.explorers = []
-         self.have_created_toolbar = False
          self.button_event_map = {}
  
      def Close(self):
          self.explorers = None
  
--- 1117,1125 ----
          self.manager = manager
          self.explorers = []
          self.button_event_map = {}
  
      def Close(self):
+         while self.explorers:
+             self._DoDeadExplorer(self.explorers[0])
          self.explorers = None
  
***************
*** 1228,1231 ****
--- 1224,1232 ----
                  # still screw up.
                  self.manager.LogDebug(0, "*** SpamBayes is NOT enabled, so will not filter incoming mail. ***")
+             if connectMode == constants.ext_cm_AfterStartup:
+                 # We are being enabled after startup, which means we don't get
+                 # the 'OnStartupComplete()' event - call it manually so we
+                 # bootstrap code that can't happen until startup is complete.
+                 self.OnStartupComplete(None)
          except:
              print "Error connecting to Outlook!"
***************
*** 1331,1336 ****
                  hook.Close()
              self.folder_hooks = None
!         self.application = None
!         self.explorers_events = None
          if self.manager is not None:
              # Save database - bsddb databases will generally do nothing here
--- 1332,1338 ----
                  hook.Close()
              self.folder_hooks = None
!         if self.explorers_events is not None:
!             self.explorers_events.Close()
!             self.explorers_events = None
          if self.manager is not None:
              # Save database - bsddb databases will generally do nothing here
***************
*** 1344,1347 ****
--- 1346,1370 ----
              self.manager = None
  
+         if mode==constants.ext_dm_UserClosed:
+             # The user has de-selected us.  Remove the toolbars we created
+             # (Maybe we can exploit this later to remove toolbars as part
+             # of uninstall?)
+             print "SpamBayes is being manually disabled - deleting toolbar"
+             try:
+                 explorers = self.application.Explorers
+                 for i in range(explorers.Count):
+                     explorer = explorers.Item(i+1)
+                     try:
+                         toolbar = explorer.CommandBars.Item(toolbar_name)
+                     except pythoncom.com_error:
+                         print "Could not find our toolbar to delete!"
+                     else:
+                         toolbar.Delete()
+             except:
+                 print "ERROR deleting toolbar"
+                 traceback.print_exc()
+ 
+         self.application = None
+ 
          print "Addin terminating: %d COM client and %d COM servers exist." \
                % (pythoncom._GetInterfaceCount(), pythoncom._GetGatewayCount())
***************
*** 1373,1377 ****
  
  def _DoRegister(klass, root):
-     import _winreg
      key = _winreg.CreateKey(root,
                              "Software\\Microsoft\\Office\\Outlook\\Addins")
--- 1396,1399 ----
***************
*** 1382,1404 ****
      _winreg.SetValueEx(subkey, "FriendlyName", 0, _winreg.REG_SZ, "SpamBayes")
  
! def RegisterAddin(klass):
!     import _winreg
!     # Try and register twice - once in HKLM, and once in HKCU.  This seems
!     # to help roaming profiles, etc.  Once registered, it is both registered
!     # on this machine for the current user (even when they roam, assuming it
!     # has been installed on the remote machine also) and for any user on this
!     # machine.
!     try:
          _DoRegister(klass, _winreg.HKEY_LOCAL_MACHINE)
      except WindowsError:
-         # But they may not have the rights to install there.
          pass
-     # We don't catch exception registering just for this user though
-     # that is fatal!
      _DoRegister(klass, _winreg.HKEY_CURRENT_USER)
      print "Registration complete."
  
! def UnregisterAddin(klass):
!     import _winreg
      try:
          _winreg.DeleteKey(_winreg.HKEY_LOCAL_MACHINE,
--- 1404,1452 ----
      _winreg.SetValueEx(subkey, "FriendlyName", 0, _winreg.REG_SZ, "SpamBayes")
  
! # Note that Addins can be registered either in HKEY_CURRENT_USER or
! # HKEY_LOCAL_MACHINE.  If the former, then:
! # * Only available for the user that installed the addin.
! # * Appears in the 'COM Addins' list, and can be removed by the user.
! # If HKEY_LOCAL_MACHINE:
! # * Available for every user who uses the machine.  This is useful for site
! #   admins, so it works with "roaming profiles" as users move around.
! # * Does not appear in 'COM Addins', and thus can not be disabled by the user.
! 
! # Note that if the addin is registered in both places, it acts as if it is
! # only installed in HKLM - ie, does not appear in the addins list.
! # For this reason, the addin can be registered in HKEY_LOCAL_MACHINE
! # by executing 'regsvr32 /i:hkey_local_machine outlook_addin.dll'
! # (or 'python addin.py hkey_local_machine' for source code users.
! # Note to Binary Builders: You need py2exe dated 8-Dec-03+ for this to work.
! 
! # Called when "regsvr32 /i:whatever" is used.  We support 'hkey_local_machine'
! def DllInstall(bInstall, cmdline):
!     klass = OutlookAddin
!     if bInstall and cmdline.lower().find('hkey_local_machine')>=0:
!         # Unregister the old installation, if one exists.
!         DllUnregisterServer()
!         # Don't catch exceptions here - if it fails, the Dll registration
!         # must fail.
          _DoRegister(klass, _winreg.HKEY_LOCAL_MACHINE)
+         print "Registration (in HKEY_LOCAL_MACHINE) complete."
+     
+ def DllRegisterServer():
+     klass = OutlookAddin
+     # *sigh* - we used to *also* register in HKLM, but as above, this makes
+     # things work like we are *only* installed in HKLM.  Thus, we explicitly
+     # remove the HKLM registration here (but it can be re-added - see the
+     # notes above.)
+     try:
+         _winreg.DeleteKey(_winreg.HKEY_LOCAL_MACHINE,
+                           "Software\\Microsoft\\Office\\Outlook\\Addins\\" \
+                           + klass._reg_progid_)
      except WindowsError:
          pass
      _DoRegister(klass, _winreg.HKEY_CURRENT_USER)
      print "Registration complete."
  
! def DllUnregisterServer():
!     klass = OutlookAddin
!     # Try to remove the HKLM version.
      try:
          _winreg.DeleteKey(_winreg.HKEY_LOCAL_MACHINE,
***************
*** 1415,1429 ****
          pass
  
- def DllRegisterServer():
-     RegisterAddin(OutlookAddin)
- 
- def DllUnregisterServer():
-     UnregisterAddin(OutlookAddin)
- 
  if __name__ == '__main__':
      import win32com.server.register
      win32com.server.register.UseCommandLine(OutlookAddin)
      if "--unregister" in sys.argv:
          DllUnregisterServer()
      else:
          DllRegisterServer()
--- 1463,1483 ----
          pass
  
  if __name__ == '__main__':
      import win32com.server.register
      win32com.server.register.UseCommandLine(OutlookAddin)
+     # todo - later win32all versions of  UseCommandLine support
+     # finalize_register and finalize_unregister keyword args, passing the
+     # functions.
+     # (But DllInstall may get support in UseCommandLine later, so let's
+     # wait and see)
      if "--unregister" in sys.argv:
          DllUnregisterServer()
      else:
          DllRegisterServer()
+         # Support 'hkey_local_machine' on the commandline, to work in
+         # the same way as 'regsvr32 /i:hkey_local_machine' does.
+         # regsvr32 calls it after DllRegisterServer, (and our registration
+         # logic relies on that) so we will too.
+         for a in sys.argv[1:]:
+             if a.lower()=='hkey_local_machine':
+                 DllInstall(True, 'hkey_local_machine')





More information about the Spambayes-checkins mailing list