regedit.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. # Regedit - a Registry Editor for Python
  2. import win32api, win32ui, win32con, commctrl
  3. from pywin.mfc import window, docview, dialog
  4. import hierlist
  5. import regutil
  6. import string
  7. def SafeApply( fn, args, err_desc = "" ):
  8. try:
  9. fn(*args)
  10. return 1
  11. except win32api.error, exc:
  12. msg = "Error " + err_desc + "\r\n\r\n" + exc.strerror
  13. win32ui.MessageBox(msg)
  14. return 0
  15. class SplitterFrame(window.MDIChildWnd):
  16. def __init__(self):
  17. # call base CreateFrame
  18. self.images = None
  19. window.MDIChildWnd.__init__(self)
  20. def OnCreateClient(self, cp, context):
  21. splitter = win32ui.CreateSplitter()
  22. doc = context.doc
  23. frame_rect = self.GetWindowRect()
  24. size = ((frame_rect[2] - frame_rect[0]),
  25. (frame_rect[3] - frame_rect[1])//2)
  26. sub_size = (size[0]//3, size[1])
  27. splitter.CreateStatic (self, 1, 2)
  28. # CTreeControl view
  29. self.keysview = RegistryTreeView(doc)
  30. # CListControl view
  31. self.valuesview = RegistryValueView(doc)
  32. splitter.CreatePane (self.keysview, 0, 0, (sub_size))
  33. splitter.CreatePane (self.valuesview, 0, 1, (0,0)) # size ignored.
  34. splitter.SetRowInfo(0, size[1] ,0)
  35. # Setup items in the imagelist
  36. return 1
  37. def OnItemDoubleClick(self, info, extra):
  38. (hwndFrom, idFrom, code) = info
  39. if idFrom==win32ui.AFX_IDW_PANE_FIRST:
  40. # Tree control
  41. return None
  42. elif idFrom==win32ui.AFX_IDW_PANE_FIRST + 1:
  43. item = self.keysview.SelectedItem()
  44. self.valuesview.EditValue(item)
  45. return 0
  46. # List control
  47. else:
  48. return None # Pass it on
  49. def PerformItemSelected(self,item):
  50. return self.valuesview.UpdateForRegItem(item)
  51. def OnDestroy(self, msg):
  52. window.MDIChildWnd.OnDestroy(self, msg)
  53. if self.images:
  54. self.images.DeleteImageList()
  55. self.images = None
  56. class RegistryTreeView(docview.TreeView):
  57. def OnInitialUpdate(self):
  58. rc = self._obj_.OnInitialUpdate()
  59. self.frame = self.GetParent().GetParent()
  60. self.hierList = hierlist.HierListWithItems( self.GetHLIRoot(), win32ui.IDB_HIERFOLDERS, win32ui.AFX_IDW_PANE_FIRST)
  61. self.hierList.HierInit(self.frame, self.GetTreeCtrl())
  62. self.hierList.SetStyle(commctrl.TVS_HASLINES | commctrl.TVS_LINESATROOT | commctrl.TVS_HASBUTTONS)
  63. self.hierList.PerformItemSelected = self.PerformItemSelected
  64. self.frame.HookNotify(self.frame.OnItemDoubleClick, commctrl.NM_DBLCLK)
  65. self.frame.HookNotify(self.OnItemRightClick, commctrl.NM_RCLICK)
  66. # self.HookMessage(self.OnItemRightClick, win32con.WM_RBUTTONUP)
  67. def GetHLIRoot(self):
  68. doc = self.GetDocument()
  69. regroot = doc.root
  70. subkey = doc.subkey
  71. return HLIRegistryKey(regroot, subkey, "Root")
  72. def OnItemRightClick(self, notify_data, extra):
  73. # First select the item we right-clicked on.
  74. pt = self.ScreenToClient(win32api.GetCursorPos())
  75. flags, hItem = self.HitTest(pt)
  76. if hItem==0 or commctrl.TVHT_ONITEM & flags==0:
  77. return None
  78. self.Select(hItem, commctrl.TVGN_CARET)
  79. menu = win32ui.CreatePopupMenu()
  80. menu.AppendMenu(win32con.MF_STRING|win32con.MF_ENABLED,1000, "Add Key")
  81. menu.AppendMenu(win32con.MF_STRING|win32con.MF_ENABLED,1001, "Add Value")
  82. menu.AppendMenu(win32con.MF_STRING|win32con.MF_ENABLED,1002, "Delete Key")
  83. self.HookCommand(self.OnAddKey, 1000)
  84. self.HookCommand(self.OnAddValue, 1001)
  85. self.HookCommand(self.OnDeleteKey, 1002)
  86. menu.TrackPopupMenu(win32api.GetCursorPos()) # track at mouse position.
  87. return None
  88. def OnDeleteKey(self,command, code):
  89. hitem = self.hierList.GetSelectedItem()
  90. item = self.hierList.ItemFromHandle(hitem)
  91. msg = "Are you sure you wish to delete the key '%s'?" % (item.keyName,)
  92. id = win32ui.MessageBox(msg, None, win32con.MB_YESNO)
  93. if id != win32con.IDYES:
  94. return
  95. if SafeApply(win32api.RegDeleteKey, (item.keyRoot, item.keyName), "deleting registry key" ):
  96. # Get the items parent.
  97. try:
  98. hparent = self.GetParentItem(hitem)
  99. except win32ui.error:
  100. hparent = None
  101. self.hierList.Refresh(hparent)
  102. def OnAddKey(self,command, code):
  103. from pywin.mfc import dialog
  104. val = dialog.GetSimpleInput("New key name", '', "Add new key")
  105. if val is None: return # cancelled.
  106. hitem = self.hierList.GetSelectedItem()
  107. item = self.hierList.ItemFromHandle(hitem)
  108. if SafeApply(win32api.RegCreateKey, (item.keyRoot, item.keyName + "\\" + val)):
  109. self.hierList.Refresh(hitem)
  110. def OnAddValue(self,command, code):
  111. from pywin.mfc import dialog
  112. val = dialog.GetSimpleInput("New value", "", "Add new value")
  113. if val is None: return # cancelled.
  114. hitem = self.hierList.GetSelectedItem()
  115. item = self.hierList.ItemFromHandle(hitem)
  116. if SafeApply(win32api.RegSetValue, (item.keyRoot, item.keyName, win32con.REG_SZ, val)):
  117. # Simply re-select the current item to refresh the right spitter.
  118. self.PerformItemSelected(item)
  119. # self.Select(hitem, commctrl.TVGN_CARET)
  120. def PerformItemSelected(self, item):
  121. return self.frame.PerformItemSelected(item)
  122. def SelectedItem(self):
  123. return self.hierList.ItemFromHandle(self.hierList.GetSelectedItem())
  124. def SearchSelectedItem(self):
  125. handle = self.hierList.GetChildItem(0)
  126. while 1:
  127. # print "State is", self.hierList.GetItemState(handle, -1)
  128. if self.hierList.GetItemState(handle, commctrl.TVIS_SELECTED):
  129. # print "Item is ", self.hierList.ItemFromHandle(handle)
  130. return self.hierList.ItemFromHandle(handle)
  131. handle = self.hierList.GetNextSiblingItem(handle)
  132. class RegistryValueView(docview.ListView):
  133. def OnInitialUpdate(self):
  134. hwnd = self._obj_.GetSafeHwnd()
  135. style = win32api.GetWindowLong(hwnd, win32con.GWL_STYLE);
  136. win32api.SetWindowLong(hwnd, win32con.GWL_STYLE, (style & ~commctrl.LVS_TYPEMASK) | commctrl.LVS_REPORT);
  137. itemDetails = (commctrl.LVCFMT_LEFT, 100, "Name", 0)
  138. self.InsertColumn(0, itemDetails)
  139. itemDetails = (commctrl.LVCFMT_LEFT, 500, "Data", 0)
  140. self.InsertColumn(1, itemDetails)
  141. def UpdateForRegItem(self, item):
  142. self.DeleteAllItems()
  143. hkey = win32api.RegOpenKey(item.keyRoot, item.keyName)
  144. try:
  145. valNum = 0
  146. ret = []
  147. while 1:
  148. try:
  149. res = win32api.RegEnumValue(hkey, valNum)
  150. except win32api.error:
  151. break
  152. name = res[0]
  153. if not name: name = "(Default)"
  154. self.InsertItem(valNum, name)
  155. self.SetItemText(valNum, 1, str(res[1]))
  156. valNum = valNum + 1
  157. finally:
  158. win32api.RegCloseKey(hkey)
  159. def EditValue(self, item):
  160. # Edit the current value
  161. class EditDialog(dialog.Dialog):
  162. def __init__(self, item):
  163. self.item = item
  164. dialog.Dialog.__init__(self, win32ui.IDD_LARGE_EDIT)
  165. def OnInitDialog(self):
  166. self.SetWindowText("Enter new value")
  167. self.GetDlgItem(win32con.IDCANCEL).ShowWindow(win32con.SW_SHOW)
  168. self.edit = self.GetDlgItem(win32ui.IDC_EDIT1)
  169. # Modify the edit windows style
  170. style = win32api.GetWindowLong(self.edit.GetSafeHwnd(), win32con.GWL_STYLE)
  171. style = style & (~win32con.ES_WANTRETURN)
  172. win32api.SetWindowLong(self.edit.GetSafeHwnd(), win32con.GWL_STYLE, style)
  173. self.edit.SetWindowText(str(self.item))
  174. self.edit.SetSel(-1)
  175. return dialog.Dialog.OnInitDialog(self)
  176. def OnDestroy(self,msg):
  177. self.newvalue = self.edit.GetWindowText()
  178. try:
  179. index = self.GetNextItem(-1, commctrl.LVNI_SELECTED)
  180. except win32ui.error:
  181. return # No item selected.
  182. if index==0:
  183. keyVal = ""
  184. else:
  185. keyVal = self.GetItemText(index,0)
  186. # Query for a new value.
  187. try:
  188. newVal = self.GetItemsCurrentValue(item, keyVal)
  189. except TypeError, details:
  190. win32ui.MessageBox(details)
  191. return
  192. d = EditDialog(newVal)
  193. if d.DoModal()==win32con.IDOK:
  194. try:
  195. self.SetItemsCurrentValue(item, keyVal, d.newvalue)
  196. except win32api.error, exc:
  197. win32ui.MessageBox("Error setting value\r\n\n%s" % exc.strerror)
  198. self.UpdateForRegItem(item)
  199. def GetItemsCurrentValue(self, item, valueName):
  200. hkey = win32api.RegOpenKey(item.keyRoot, item.keyName)
  201. try:
  202. val, type = win32api.RegQueryValueEx(hkey, valueName)
  203. if type != win32con.REG_SZ:
  204. raise TypeError("Only strings can be edited")
  205. return val
  206. finally:
  207. win32api.RegCloseKey(hkey)
  208. def SetItemsCurrentValue(self, item, valueName, value):
  209. # ** Assumes already checked is a string.
  210. hkey = win32api.RegOpenKey(item.keyRoot, item.keyName , 0, win32con.KEY_SET_VALUE)
  211. try:
  212. win32api.RegSetValueEx(hkey, valueName, 0, win32con.REG_SZ, value)
  213. finally:
  214. win32api.RegCloseKey(hkey)
  215. class RegTemplate(docview.DocTemplate):
  216. def __init__(self):
  217. docview.DocTemplate.__init__(self, win32ui.IDR_PYTHONTYPE, None, SplitterFrame, None)
  218. # def InitialUpdateFrame(self, frame, doc, makeVisible=1):
  219. # self._obj_.InitialUpdateFrame(frame, doc, makeVisible) # call default handler.
  220. # frame.InitialUpdateFrame(doc, makeVisible)
  221. def OpenRegistryKey(self, root = None, subkey = None): # Use this instead of OpenDocumentFile.
  222. # Look for existing open document
  223. if root is None: root = regutil.GetRootKey()
  224. if subkey is None: subkey = regutil.BuildDefaultPythonKey()
  225. for doc in self.GetDocumentList():
  226. if doc.root==root and doc.subkey==subkey:
  227. doc.GetFirstView().ActivateFrame()
  228. return doc
  229. # not found - new one.
  230. doc = RegDocument(self, root, subkey)
  231. frame = self.CreateNewFrame(doc)
  232. doc.OnNewDocument()
  233. self.InitialUpdateFrame(frame, doc, 1)
  234. return doc
  235. class RegDocument (docview.Document):
  236. def __init__(self, template, root, subkey):
  237. docview.Document.__init__(self, template)
  238. self.root = root
  239. self.subkey = subkey
  240. self.SetTitle("Registry Editor: " + subkey)
  241. def OnOpenDocument (self, name):
  242. raise TypeError("This template can not open files")
  243. return 0
  244. class HLIRegistryKey(hierlist.HierListItem):
  245. def __init__( self, keyRoot, keyName, userName ):
  246. self.keyRoot = keyRoot
  247. self.keyName = keyName
  248. self.userName = userName
  249. hierlist.HierListItem.__init__(self)
  250. def __lt__(self, other):
  251. return self.name < other.name
  252. def __eq__(self, other):
  253. return self.keyRoot==other.keyRoot and \
  254. self.keyName == other.keyName and \
  255. self.userName == other.userName
  256. def __repr__(self):
  257. return "<%s with root=%s, key=%s>" % (self.__class__.__name__, self.keyRoot, self.keyName)
  258. def GetText(self):
  259. return self.userName
  260. def IsExpandable(self):
  261. # All keys are expandable, even if they currently have zero children.
  262. return 1
  263. ## hkey = win32api.RegOpenKey(self.keyRoot, self.keyName)
  264. ## try:
  265. ## keys, vals, dt = win32api.RegQueryInfoKey(hkey)
  266. ## return (keys>0)
  267. ## finally:
  268. ## win32api.RegCloseKey(hkey)
  269. def GetSubList(self):
  270. hkey = win32api.RegOpenKey(self.keyRoot, self.keyName)
  271. win32ui.DoWaitCursor(1)
  272. try:
  273. keyNum = 0
  274. ret = []
  275. while 1:
  276. try:
  277. key = win32api.RegEnumKey(hkey, keyNum)
  278. except win32api.error:
  279. break
  280. ret.append(HLIRegistryKey(self.keyRoot, self.keyName + "\\" + key, key))
  281. keyNum = keyNum + 1
  282. finally:
  283. win32api.RegCloseKey(hkey)
  284. win32ui.DoWaitCursor(0)
  285. return ret
  286. template = RegTemplate()
  287. def EditRegistry(root = None, key = None):
  288. doc=template.OpenRegistryKey(root, key)
  289. if __name__=='__main__':
  290. EditRegistry()