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. from . 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 as 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 as 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 as 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()