Opens same registry twice? - python

I am trying to get all installed programs of my windows computer, therefore I read out the registry.
But somehow python reads the 32bit programs out twice (even though I give him another registry entry)
Here is the code snipped:
def get_programs(registry):
reg = ConnectRegistry(None, HKEY_LOCAL_MACHINE)
programList = []
key = OpenKey(reg, registry)
print(QueryInfoKey(key))
for i in range(0, QueryInfoKey(key)[0]):
programList.append(EnumKey(key, i))
CloseKey(key)
CloseKey(reg)
return programList
I call this function like this:
registry32bit = "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
registry64bit = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
programs32bit = get_programs(registry32bit)
programs64bit = get_programs(registry64bit)
Why does python open and read out the same registry (for 32 bit) twice and return the exactly same list?

This appears to work and uses #eryksun suggestion in a comment below about just letting the redirection happen and not explicitly referencing the Wow6432Node registry key. The central idea is to just specify either the KEY_WOW64_32KEY or KEY_WOW64_64KEY flag when opening the uninstall subkey and let the magic happen.
Note: I also Pythonized the code in the get_programs() function some. This made it shorter and more readable in my opinion.
import sys
from _winreg import *
# Assure registry handle objects with context manager protocol implemented.
if sys.version_info.major*10 + sys.version_info.minor < 26:
raise AssertionError('At least Python 2.6 is required.')
def get_programs(subkey, regBitView):
with ConnectRegistry(None, HKEY_LOCAL_MACHINE) as hive:
with OpenKey(hive, subkey, 0, regBitView | KEY_READ) as key:
return [EnumKey(key, i) for i in range(QueryInfoKey(key)[0])]
UNINSTALL_REG_KEY = r'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall'
programs32bit = get_programs(UNINSTALL_REG_KEY, KEY_WOW64_32KEY)
programs64bit = get_programs(UNINSTALL_REG_KEY, KEY_WOW64_64KEY)
print('32-bit programs:\n{}'.format(programs32bit))
print('')
print('64-bit programs:\n{}'.format(programs64bit))
Many thanks to #eryksun for the clues and many implementation strategy suggestions.

Related

Python 3.6: "AttributeError: 'SimpleQueue' object has no attribute '_poll'"

When I use a standard Queue to send samples to a process, everything works fine. However, since my needs are simple, I tried to use a SimpleQueue and for some reason the 'empty' method doesn't work. Here's the details:
Error comes from the consumer process (when sample_queue is Queue, everything works, when sample_queue is SimpleQueue, things break):
def frame_update(i):
while not self.sample_queue.empty():
sample = self.sample_queue.get()
for line in lines:
While executing sample_queue.empty() -- SimpleQueue.empty(), from Python 3.6 on windows (queues.py) we get:
def empty(self):
return not self._poll()
Where self._poll() has been set in init by:
def __init__(self, *, ctx):
self._reader, self._writer = connection.Pipe(duplex=False)
self._rlock = ctx.Lock()
self._poll = self._reader.poll
if sys.platform == 'win32':
self._wlock = None
else:
self._wlock = ctx.Lock()
So I follow the self._reader which is set from connection.Pipe (connection.py):
...
c1 = PipeConnection(h1, writable=duplex)
c2 = PipeConnection(h2, readable=duplex)
Ok, great. The _reader is going to be a PipeConnection and pipe connection has this method:
def _poll(self, timeout):
if (self._got_empty_message or
_winapi.PeekNamedPipe(self._handle)[0] != 0):
return True
return bool(wait([self], timeout))
Alright -- So a couple of questions:
1) Shouldn't the init of SimpleQueue be assigning self.poll to self._reader._poll instead of self._reader.poll? Or am I missing something in the inheritance hierarchy?
2) The PipeConnection _poll routine takes a timeout parameter, so #1 shouldn't work...
*) -- Is there some other binding of PipeConnection _poll that I'm missing?
Am I missing something? I am using Python3.6, Windows, debugging in PyCharm and I follow all the paths and they're in the standard multiprocessing paths. I'd appreciate any help or advice. Thanks!
EDIT: After further review, I can see that PipeConnection is a subclass of _ConnectionBase which does indeed have a 'poll' method and it is bound with a default timeout parameter.
So the question is: When SimpleQueue is initializing and sets
self._poll = self._reader.poll
Why doesn't it go up the class hierarchy to grab that from _ConnectionBase?
After looking at why the Queue type works and why the SimpleQueue doesn't, I found that Queue sets the _poll method 'after_fork' as well as before. SimpleQueue doesn't. By changing the setstate method to add self._poll = self._reader.poll as follows (queues.py, line 338), SimpleQueue works
def __setstate__(self, state):
(self._reader, self._writer, self._rlock, self._wlock) = state
self._poll = self._reader.poll
Seems like a bug to me unless I'm really misunderstanding something. I'll submit a bug report and reference this post. Hope this helps someone!
http://bugs.python.org/issue30301

Use Python to Edit Windows 8 Power Options

The Problem:
Every time I restart my computer my Windows 8 power settings go back to default and puts my computer to sleep after an hour. I don't want my computer to ever go to sleep unless I say so... I have to go in Control Panel > System and Security > Power Options > Edit Plan Settings and manually edit the put the computer to sleep setting to Never.
What I want:
A Python script to edit the Power Options in Windows 8. I will set it to run every time I reboot.
I've searched for a Python module to edit Windows settings but couldn't find what I was looking for. I've played with win32api to control my courser a while back but couldn't find Power Options in its documentation.
Julius Caesar's hint about using powercfg command-line options was perfect.
Here is the simple script I ended up using:
import subprocess
subprocess.call("powercfg -change -standby-timeout-ac 0")
The -standby-timeout-ac option is set to zero so my computer will Never go to sleep
I think You should look into powercfg Windows' command and set whatever You like with python's subprocess.call, for example:
import subprocess
subprocess.call("powercfg -change -monitor-timeout-ac 666")
I guess it is pretty self-explanatory: change '-ac' to '-dc' for battery setting, value is in minutes and zero stands for infinity, obviously.
I had a solution which heavily involve with win32com.client
It is work on windows 10
import win32com.client
class PowerPlan(Computer):
def __init__(self, mk="//./root/cimv2/power"):
super(PowerPlan, self).__init__(mk)
self.power_info = None
self.power_plan = None
def get_active_power_plan(self) -> str:
power_plans = self.wmi.InstancesOf("Win32_powerplan")
for plan in power_plans:
if plan.IsActive:
match = re.search(r'\{(.+?)\}', plan.InstanceID)
self.power_plan = plan
return match.group(1)
def get_power_plan_index(self, guid_id):
unknown_list = []
current_power_plan_index = {"AC": {}, "DC": {}}
power_index = self.wmi.InstancesOf("Win32_powersettingdataindex")
for power_value in power_index:
# print(type(power_value))
# print(dir(power_value))
match = re.search(guid_id, power_value.InstanceID)
if match is not None:
match = re.search(guid_id + r'\}\\(\w{2})\\\{(.+?)\}', power_value.InstanceID)
power_mode = match.group(1)
power_tag = match.group(2)
try:
power_word = PowerPlanGUID(power_tag).name
except Exception as Err:
# print("Unknown Tag GUID: " + power_tag)
if power_tag not in unknown_list:
unknown_list.append(power_tag)
continue
# power_info = {power_word : power_value.settingindexvalue}
current_power_plan_index[power_mode][power_word] = power_value.settingindexvalue
self.power_info = current_power_plan_index
self._json_dump(self.power_info)
def set_power_plan_value(self, act_plan_guid, power_mode, power_plan_value_guid, value):
power_index = self.wmi.InstancesOf("Win32_powersettingdataindex")
for power_setting in power_index:
match = re.search(act_plan_guid + r'\}\\' + power_mode + r'\\\{' + power_plan_value_guid + r'\}',
power_setting.InstanceID)
# match = re.search(power_plan_value_guid, power_setting.InstanceID)
if match is not None:
print(power_setting.InstanceID)
print(power_setting.settingindexvalue)
# Properties_
power_setting.Properties_("SettingIndexValue").Value = value
# How to make the changed value work
power_setting.Put_()
act_method = self.power_plan.Methods_("Activate")
self.power_plan.ExecMethod_("Activate")
else:
pass
I know it's a bit late, but there has been a new module published named "powerplan".
pip install powerplan
Then import the module:
import powerplan
To get your current power plan scheme use:
print(powerplan.get_current_scheme_name())
print(powerplan.get_current_scheme_guid())
To change your power plan scheme use:
powerplan.change_current_scheme_to_powersaver()
powerplan.change_current_scheme_to_balanced()
powerplan.change_current_scheme_to_high()

Python Cmd Tab Completion Problems

I've got an application I'm currently working on for our company. Its currently built around Python's Cmd module, and features tab-completion for a number of tasks.
For some reason however, the Tab completion only currently works on one machine in the building - running the scripts from other machines doesn't allow the tab completion.
Here's the offending code parts:
def populate_jobs_list():
global avail_jobs
avail_jobs = os.walk(rootDir()).next()[1]
print avail_jobs
...
def complete_job(self, text, line, start_index, end_index):
global avail_jobs
populate_jobs_list()
if text:
return [
jobs for jobs in avail_jobs
if jobs.startswith(text)
]
else:
return avail_jobs
def do_job(self, args):
pass
split_args = args.rsplit()
os.environ['JOB'] = args
job_dir = os.path.join( rootDir(), os.getenv('JOB'))
os.environ['JOB_PROPS'] = (job_dir + '\\job_format.opm')
if not os.path.isdir(job_dir):
print 'Job does not exist. Try again.'
return
else:
print('Jobbed into: ' + os.getenv('JOB'))
return
populate_jobs_list()
prompt = outPrompt()
prompt.prompt = '\> '
prompt.cmdloop('Loading...')
Am I missing something obvious here? Just to clarify, on machine A, the tab completion works as intended. When its run on any other machine in the building, it fails to complete.
Check if the environment variable PYTHONSTARTUP is set properly. It should point to a script which in turn needs to do sth like this:
try:
import readline
except ImportError:
sys.stdout.write("No readline module found, no tab completion available.\n")
else:
import rlcompleter
readline.parse_and_bind('tab: complete')
Maybe (some part of) this is only done properly on the one working machine?
Maybe the readline module is available only on the one working machine?

How to determine if win32api.ShellExecute was successful using hinstance?

I've been looking around for an answer to my original issue.. how do i determine (programmatically) that my win32api.ShellExecute statement executed successfully, and if a successful execution occurs, execute an os.remove() statement.
Researching I found out that the ShellExecute() call returns the HINSTANCE. Further digging I found that ShellExecute() will return an HINSTANCE > 32 if it was successful. My problem/question now is, how do i use it to control the rest of my program's flow? I tried using an if HINSTANCE> 32: statement to control the next part, but I get a NameError: name 'hinstance' is not defined message. Normally this wouldn't confuse me because it means i need to define the variable 'hinstance' before referencing it; however, because i thought ShellExecute is supposed to return HINSTANCE, i thought that makes it available for use?
Here is my full code where i am trying to implement this. Note that in my print_file() def i am assigning hinstance to the full win32api.ShellExecute() command in attempt to capture the hinstance along with explicitly returning it at the end of the function.. this isn't working either.
import win32print
import win32api
from os.path import isfile, join
import glob
import os
import time
source_path = "c:\\temp\\source\\"
def main():
printer_name = win32print.GetDefaultPrinter()
while True:
file_queue = [f for f in glob.glob("%s\\*.txt" % source_path) if isfile(f)]
if len(file_queue) > 0:
for i in file_queue:
print_file(i, printer_name)
if hinstance > 32:
time.sleep(.25)
delete_file(i)
print "Filename: %r has printed" % i
print
time.sleep(.25)
print
else:
print "No files to print. Will retry in 15 seconds"
time.sleep(15)
def print_file(pfile, printer):
hinstance = win32api.ShellExecute(
0,
"print",
'%s' % pfile,
'/d:"%s"' % printer,
".",
0
)
return hinstance
def delete_file(f):
os.remove(f)
print f, "was deleted!"
def alert(email):
pass
main()
With ShellExecute, you will never know when the printing is complete, it depends on the size of the file and whether the printer driver buffers the contents (the printer might be waiting for you to fill the paper tray, for example).
According to this SO answer, it looks like subprocess.call() is a better solution, since it waits for the command to complete, only in this case you would need to read the registry to obtain the exe associated with the file.
ShellExecuteEx is available from pywin32, you can do something like:
import win32com.shell.shell as shell
param = '/d:"%s"' % printer
shell.ShellExecuteEx(fmask = win32com.shell.shellcon.SEE_MASK_NOASYNC, lpVerb='print', lpFile=pfile, lpParameters=param)
EDIT: code for waiting on the handle from ShellExecuteEx()
import win32com.shell.shell as shell
import win32event
#fMask = SEE_MASK_NOASYNC(0x00000100) = 256 + SEE_MASK_NOCLOSEPROCESS(0x00000040) = 64
dict = shell.ShellExecuteEx(fMask = 256 + 64, lpFile='Notepad.exe', lpParameters='Notes.txt')
hh = dict['hProcess']
print hh
ret = win32event.WaitForSingleObject(hh, -1)
print ret
The return value of ShellExecute is what you need to test. You return that from print_file, but you then ignore it. You need to capture it and check that.
hinstance = print_file(i, printer_name)
if hinstance > 32:
....
However, having your print_file function leak implementation detail like an HINSTANCE seems bad. I think you would be better to check the return value of ShellExecute directly at the point of use. So try to move the > 32 check inside print_file.
Note that ShellExecute has very weak error reporting. If you want proper error reporting then you should use ShellExecuteEx instead.
Your delete/sleep loop is very brittle indeed. I'm not quite sure I can recommend anything better since I'm not sure what you are trying to achieve. However, expect to run into trouble with that part of your program.

Python hashlib.md5 and ejabberd

I am using a python script as an external auth option in ejabberd 2.1.6.
I wanted to start encrypting the clear text passwords that come across in the auth verification, so that they are not being stored in plain text in the backend database. When I add the following code to my python script and restart ejabberd, it hangs:
import hashlib
clear = "barfoo"
salt = "foobar"
hash = hashlib.md5( salt + clear ).hexdigest()
Does hashlib require specific priviledges to run?
When I run it as a normal user (ejabberd) it works without issue. When the python script is run within the external auth of ejabberd it hangs.
I've attempted to have it write out the 'hash' to a file and it never gets there ... if i run it as the 'ejabberd' user, it writes out to file fine.
I've tried to find information about restrictions for using this library on ubuntu without any success. Any ideas?
-sd
** 22.02.2011: Here is the full script adapted from https://git.process-one.net/ejabberd/mainline/blobs/raw/2.1.x/doc/dev.html#htoc8 :
#!/usr/bin/python
import sys
from struct import *
import hashlib
def from_ejabberd():
input_length = sys.stdin.read(2)
(size,) = unpack('>h', input_length)
return sys.stdin.read(size).split(':')
def to_ejabberd(bool):
answer = 0
if bool:
answer = 1
token = pack('>hh', 2, answer)
sys.stdout.write(token)
sys.stdout.flush()
def auth(username, server, password):
clear = "barfoo"
salt = "foobar"
hash = hashlib.md5( salt + clear ).hexdigest()
if (password == hash): return True
else: return False
def isuser(username, server):
return True
def setpass(username, server, password):
return True
while True:
data = from_ejabberd()
success = False
if data[0] == "auth":
success = auth(data[1], data[2], data[3])
elif data[0] == "isuser":
success = isuser(data[1], data[2])
elif data[0] == "setpass":
success = setpass(data[1], data[2], data[3])
to_ejabberd(success)
I have been messing with the same problem. I Can't really track down the problem with openssl binings in _hashlib. Whatever the problem is, i will have to patch python distribution sources. Not really an feasible solution. So i ended up using a pycrypto wrapper for the crypto functions which don't block in this case.
pip install pycrypto
from Crypto.Hash import MD5
m = MD5.new()
m.update("%s%s" % (salt ,clear))
h.hexdigest()
I looked into the hashlib source and while it does not seem to require too much, it does import .so files as modules and one of them hits openssl. It all looks pretty safe but if ejabberd tries to fence itself against calls to 3rd party code (or if you have SELinux or something else to that effect running), stuff can conceivably get weird. I got this in a REPL:
>>> import _md5
>>> _md5.__file__
'/usr/lib/python2.7/lib-dynload/_md5module.so'
Try this on your box and then try putting
_md5 = imp.load_dynamic('_md5', '/usr/lib/python2.7/lib-dynload/_md5module.so')
Or just
import _md5
(with the appropriate path updated to yours) in your code before the offending line and with some trace statement afterwards. Try the same with _hashlib instead of _md5 (hashlib defaults to _hashlib which wraps openssl, but if it doesn't load or doesn't have the needed hash it falls back to _md5, _sha etc.). If it's not the imports that fail/hang then you can try calling _md5.new(salt + clear) and _hashlib.openssl_md5(salt + clear) and see if it's one of them.
If it is the import at fault, then possibly a similar problem was tackled here
I don't know ejabberd, so I can't relate their solution to your problem, unfortunately.
I do have to say it, though: in all python implementations I know, = instead of == in a condition would raise a SyntaxError and that's that - the program would never even enter the main while loop.
hashlib does not require anything special. What means hangs? Where does it hang? Use pdb.set_trace() to step trough the code or use 'strace' or 'ltrace' to investigate API calls.
Try to use logging module, it can help you to watch input and output data, also check scripts permissions, let executing by user which is ejabberd, or for debug just set chmod 777 external.py.

Categories

Resources