@@ -136,7 +136,7 @@ def _update_reg_values(key, data, install, exclude=set()):
136136            winreg .SetValueEx (key , k , None , v_kind , v )
137137
138138
139- def  _is_tag_managed (company_key , tag_name ):
139+ def  _is_tag_managed (company_key , tag_name ,  * ,  creating = False ):
140140    try :
141141        tag  =  winreg .OpenKey (company_key , tag_name )
142142    except  FileNotFoundError :
@@ -147,7 +147,69 @@ def _is_tag_managed(company_key, tag_name):
147147                return  True 
148148        except  FileNotFoundError :
149149            pass 
150-     return  False 
150+         if  not  creating :
151+             return  False 
152+ 
153+         # gh-11: Clean up invalid entries from other installers 
154+         # It's highly likely that our old MSI installer wouldn't properly remove 
155+         # its registry keys on uninstall, so we'll check for the InstallPath 
156+         # subkey and if it's missing, back up the key and then use it ourselves. 
157+         try :
158+             with  _reg_open (tag , "InstallPath" ) as  subkey :
159+                 if  subkey :
160+                     # if InstallPath refers to a directory that exists, 
161+                     # leave it alone. 
162+                     p  =  winreg .QueryValueEx (subkey , None )[0 ]
163+                     if  p  and  Path (p ).exists ():
164+                         return  False 
165+         except  FileNotFoundError :
166+             pass 
167+         except  OSError :
168+             # If we couldn't access it for some reason, leave it alone. 
169+             return  False 
170+ 
171+     # Existing key is almost certainly not valid, so let's rename it, 
172+     # warn the user, and then continue. 
173+     LOGGER .debug ("Key %s appears invalid, so moving it and taking it for this " 
174+                  "new install" , tag_name )
175+     try :
176+         from  _native  import  reg_rename_key 
177+     except  ImportError :
178+         LOGGER .debug ("Failed to import reg_rename_key" , exc_info = True )
179+         return  False 
180+ 
181+     parent_name , _ , orig_name  =  tag_name .replace ("/" , "\\ " ).rpartition ("\\ " )
182+     with  _reg_open (company_key , parent_name , writable = True ) as  tag :
183+         if  not  tag :
184+             # Key is no longer there, so we can use it 
185+             return  True 
186+         for  i  in  range (1000 ):
187+             try :
188+                 new_name  =  f"{ orig_name }  .{ i }  " 
189+                 # Raises standard PermissionError (5) if new_name exists 
190+                 reg_rename_key (tag .handle , orig_name , new_name )
191+                 LOGGER .warn ("An existing registry key for %s was renamed to %s " 
192+                             "because it appeared to be invalid. If this is " 
193+                             "correct, the registry key can be safely deleted. " 
194+                             "To avoid this in future, ensure that the " 
195+                             "InstallPath key refers to a valid path." ,
196+                             tag_name , new_name )
197+                 break 
198+             except  FileNotFoundError :
199+                 LOGGER .debug ("Original key disappeared, so we will claim it" )
200+                 return  True 
201+             except  PermissionError :
202+                 LOGGER .debug ("Failed to rename %s to %s" , orig_name , new_name ,
203+                              exc_info = True )
204+             except  OSError :
205+                 LOGGER .debug ("Unexpected error while renaming %s to %s" ,
206+                              orig_name , new_name , exc_info = True )
207+                 raise 
208+         else :
209+             LOGGER .warn ("Attempted to clean up invalid registry key %s but " 
210+                         "failed after too many attempts." , tag_name );
211+             return  False 
212+         return  True 
151213
152214
153215def  _split_root (root_name ):
@@ -166,7 +228,7 @@ def _split_root(root_name):
166228def  update_registry (root_name , install , data ):
167229    hive , name  =  _split_root (root_name )
168230    with  winreg .CreateKey (hive , name ) as  root :
169-         if  _is_tag_managed (root , data ["Key" ]):
231+         if  _is_tag_managed (root , data ["Key" ],  creating = True ):
170232            with  winreg .CreateKey (root , data ["Key" ]) as  tag :
171233                LOGGER .debug ("Creating/updating %s\\ %s" , root_name , data ["Key" ])
172234                winreg .SetValueEx (tag , "ManagedByPyManager" , None , winreg .REG_DWORD , 1 )
0 commit comments