I am facing difficulties in reading a registry key created by my software. However with the same code, I am able to read other keys.
installdir = winreg.OpenKey(
winreg.HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\MediaPlayer\\Player\\Extensions\\Types"
) #this works perfect
#installdir1 = winreg.OpenKey(
winreg.HKEY_LOCAL_MACHINE,
"SOFTWARE\\MySoftware\\MyEvent\\IS"
) #this gives Filenotfound error
# list values owned by this registry key
try:
i = 0
while 1:
name, value, type = winreg.EnumValue(installdir, i)
print (repr(name))
i += 1
except WindowsError:
print ("Bot donf")
value, type = winreg.QueryValueEx(installdir, "10")
print("user is", repr(value))
value, type = winreg.QueryValueEx(winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\MySoftware\\MyEvent\\IS"), "v2")
print("user is", repr(value))
Traceback shows
Traceback (most recent call last):
File "D:/python_scripts/myclass.py", line 32, in <module>
value, type = winreg.QueryValueEx(winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\MySoftware\\MyEvent\\IS"), "v2")
FileNotFoundError: [WinError 2] The system cannot find the file specified
However Windows reg query is able to retrieve the value set.
#reg query HKLM\SOFTWARE\MySoftware\MyEvent\IS /v v2
HKEY_LOCAL_MACHINE\SOFTWARE\MySoftware\MyEvent\IS
v2 REG_DWORD 0x12
Any help will be highly appreciated
There are 2 views of the registry. There is the 32-bit registry view and the 64-bit registry view. By default and in most cases, 32-bit applications will only see the the 32-bit registry view and 64-bit applications will only see the 64-bit registry view.
The other view can be accessed by using the KEY_WOW64_64KEY or the KEY_WOW64_32KEY access flags.
If you are running 32-bit python and your key is part of the 64-bit registry view, you should use something like this to open your key:
winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\MySoftware\\MyEvent\\IS", access=winreg.KEY_READ | winreg.KEY_WOW64_64KEY)
If you are running 64-bit python and your key is part of the 32-bit registry view, you should use something like this to open your key:
winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\MySoftware\\MyEvent\\IS", access=winreg.KEY_READ | winreg.KEY_WOW64_32KEY)
If you know the key is always part of the same view, adding the proper KEY_WOW64_* access flag will ensure that it works no matter what your python architecture is.
In the most generic case, if you have variable python architecture and you do not know in advance in which view the key will be, you can try finding the key in your current view and try the other view next. It could look something like this:
try:
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\MySoftware\\MyEvent\\IS")
except FileNotFoundError:
import platform
bitness = platform.architecture()[0]
if bitness == '32bit':
other_view_flag = winreg.KEY_WOW64_64KEY
elif bitness == '64bit':
other_view_flag = winreg.KEY_WOW64_32KEY
try:
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\MySoftware\\MyEvent\\IS", access=winreg.KEY_READ | other_view_flag)
except FileNotFoundError:
'''
We really could not find the key in both views.
'''
For more information, check out Accessing an Alternate Registry View.
Related
I'm getting an error trying of use the code of this link: Data Catalog Example. At the step 4, just copy pasting all the code provided, authenticating into my GCP Project and testing it.
Everything is ok until it start creating tag template fields...
tag_template = datacatalog_v1.types.TagTemplate()
tag_template.display_name = 'On-premises Tag Template'
tag_template.fields['source'].display_name = 'Source of the data asset'
tag_template.fields['source'].type.primitive_type = \
datacatalog_v1.FieldType.PrimitiveType.STRING.value
it always crash with the same error.
Error Image
tag_template <proto.marshal.collections.maps.MapComposite object at 0x10fe23310>
Traceback (most recent call last):
File "/Users/ac/Documents/DataCatalog/python_datacatalog/application/sample.py", line 149, in <module>
tag_template.fields['source'].display_name = 'Source of the data asset'
File "/Users/ac/Documents/DataCatalog/python_datacatalog/venv/lib/python3.8/site-packages/proto/marshal/collections/maps.py", line 56, in __getitem__
raise KeyError(key)
KeyError: 'source'
Someone can help me sharing alternatives to do this?
The sample code on the Data Catalog Example is outdated. Did a few changes on the code starting at step 4 (where you are currently stuck). I encountered another error at the next line for primitive type.
# -------------------------------
# 4. Create a Tag Template.
# -------------------------------
tag_template = datacatalog_v1.types.TagTemplate()
tag_template.display_name = 'On-premises Tag Template'
tag_template.fields['source'] = datacatalog_v1.types.TagTemplateField() #creates key 'source'
tag_template.fields['source'].display_name = 'Source of the data asset'
tag_template.fields['source'].type_.primitive_type = datacatalog_v1.types.FieldType.PrimitiveType.STRING #from type -> type_, syntax for primitive type string
Fix is to create the key 'source' for TagTemplateField by adding tag_template.fields['source'] = datacatalog_v1.types.TagTemplateField()
Updated the syntax for "tag_template.type" and assigning primitive string value
If you proceed to step 5, an error will pop up KeyError: 'source'. If you did not encounter this then it is all good. But if ever you encounter it here is the code to fix that.
# -------------------------------
# 5. Attach a Tag to the custom Entry.
# -------------------------------
tag = datacatalog_v1.types.Tag()
tag.template = tag_template.name
tag.fields['source'] = datacatalog_v1.types.TagField() #creates key 'source'
tag.fields['source'].string_value = 'On-premises system name'
tag = datacatalog.create_tag(parent=entry.name, tag=tag)
print('Created tag: {}'.format(tag.name))
Fix is similar to step 4 which is to create the key 'source' this time for TagField by adding tag.fields['source'] = datacatalog_v1.types.TagField() #creates key 'source'
I ran the whole script from step 1 to 5.
Output of the script:
Created tag template:
Created tag:
I have a simple function that I use to read the contents of a text file into a Python variable. I use it to import SQL queries. The function takes a parameter that is the path and name of the text file and allows several attempts to get the name right, allowing for typos or mis-spellings. By default, this parameter is set to None. If the file can't be found, the function prints an error message and presents an input() box to allow a new path and filename to be entered. The function then either returns the string (representing the SQL query) or returns None if the file can't be found.
The function is:
def readQueryFromFile(queryPathAndFileName = None):
maxAttempts = 3
for i in range(maxAttempts):
if (queryPathAndFileName is None) or (i > 0):
queryPathAndFileName = input("Enter path and filename for text file contains SQL query: ")
try:
tempFileObject = open(queryPathAndFileName)
tempQuery = tempFileObject.read()
tempFileObject.close()
break
except FileNotFoundError as e:
print("\nA FileNotFoundError occurred.\nError number {0}: {1}. File named \'{2}\' does not exist at that location.".format(e.args[0],e.args[1],queryPathAndFileName))
if i < (maxAttempts-1):
print('\nPlease re-enter path and filename details.\n') # Only say 'Please try again' if not last attempt.
else:
# If query file can't be found then set tempQuery to None
print('\nFailed to find file containing query after {0} attempts.\n'.format(i+1))
tempQuery = None
return tempQuery
The function could be called in a Jupyter notebook cell using:
myQuery = readQueryFromFile(queryPathAndFileName = '/geosgnasoeg/asgogeso.sges')
Clearly, the path and file name is nonsensical and the function presents an error message and a prompt to enter the path and file name again. However, the error messages appear after the input box is displayed as follows:
Enter path and filename for text file contains SQL query: |________|
A FileNotFoundError occurred.
Error number 2: No such file or directory. File named '/geosgnasoeg/asgogeso.sges' does not exist at that location.
Please re-enter path and filename details.
Having the messages appear out of sequence can be confusing. Interestingly, if a second incorrect path and file name is entered, the output realigns itself correctly.
I'm using a Mac running El Capitan and this issues occurs in both Safari and Firefox.
Is there a way to force the output displayed in Jupyter notebook to appear in the correct (i.e. sequential) order?
I am trying to control a Tektronix RSA306 Spectrum Analyzer by using the API. The program finds the RSA300API.dll file but throws an error when searching and connecting to the device. The program I am running is an example from Tektronix. The setup I am currently using is Python 2.7.12 x64(Anaconda 4.1.1) on 64 bit Windows 7.
from ctypes import *
import numpy as np
import matplotlib.pyplot as plt
I am locating the .dll file with:
rsa300 = WinDLL("RSA300API.dll")
The error occurs when executing the search function:
longArray = c_long*10
deviceIDs = longArray()
deviceSerial = c_wchar_p('')
numFound = c_int(0)
serialNum = c_char_p('')
nomenclature = c_char_p('')
header = IQHeader()
rsa300.Search(byref(deviceIDs), byref(deviceSerial), byref(numFound))
if numFound.value == 1:
rsa300.Connect(deviceIDs[0])
else:
print('Unexpected number of instruments found.')
exit()
When running the following error messages appear:
C:\Anaconda2\python.exe C:/Tektronix/RSA_API/lib/x64/trial
<WinDLL 'RSA300API.dll', handle e47b0000 at 3ae4e80>
Traceback (most recent call last):
File "C:/Tektronix/RSA_API/lib/x64/trial", line 44, in <module>
rsa300.Search(byref(deviceIDs), byref(deviceSerial), byref(numFound))
File "C:\Anaconda2\lib\ctypes\__init__.py", line 376, in __getattr__
func = self.__getitem__(name)
File "C:\Anaconda2\lib\ctypes\__init__.py", line 381, in __getitem__
func = self._FuncPtr((name_or_ordinal, self))
AttributeError: function 'Search' not found
The issue that I am having is that the 'Search' function is not found. What would be the solution to this problem?
Tektronix application engineer here.
The problem here is a mismatch of API versions. Your code is referencing an old version of the API (RSA300API.dll) and the error message is referencing a newer version of the API (RSA_API.dll). Make sure you have installed the most current version of the API and that you reference the correct dll in your code.
Here is a link to download the latest version of the RSA API (as of 11/1/16):
http://www.tek.com/model/rsa306-software
Here is a link to download the API documentation (as of 11/1/16). There is an Excel spreadsheet attached to this document that outlines the differences between old functions and new functions:
http://www.tek.com/spectrum-analyzer/rsa306-manual-6
Function names were changed in the new version using for the sake of clarity and consistency. The old version of the API didn't have prefixes for most functions, and it was unclear which functions were grouped together just from reading the function names. The new version of the API applies prefixes to all functions and it is now much easier to tell what functional group a given function is in just by reading its declaration. For example the old search and connect functions were simply called Search() and Connect(), and the new version of the functions are called DEVICE_Search() and DEVICE_Connect().
Note: I use cdll.LoadLibrary("RSA_API.dll") to load the dll rather than WinDLL().
DEVICE_Search() has slightly different arguments than Search(). Due to different argument data types, the new DEVICE_Search() function doesn't play as well with ctypes as the old Search() function does, but I've found a method that works (see code below).
Here is the search_connect() function I use at the beginning of my RSA control scripts:
from ctypes import *
import os
"""
################################################################
C:\Tektronix\RSA306 API\lib\x64 needs to be added to the
PATH system environment variable
################################################################
"""
os.chdir("C:\\Tektronix\\RSA_API\\lib\\x64")
rsa = cdll.LoadLibrary("RSA_API.dll")
"""#################CLASSES AND FUNCTIONS#################"""
def search_connect():
#search/connect variables
numFound = c_int(0)
intArray = c_int*10
deviceIDs = intArray()
#this is absolutely asinine, but it works
deviceSerial = c_char_p('longer than the longest serial number')
deviceType = c_char_p('longer than the longest device type')
apiVersion = c_char_p('api')
#get API version
rsa.DEVICE_GetAPIVersion(apiVersion)
print('API Version {}'.format(apiVersion.value))
#search
ret = rsa.DEVICE_Search(byref(numFound), deviceIDs,
deviceSerial, deviceType)
if ret != 0:
print('Error in Search: ' + str(ret))
exit()
if numFound.value < 1:
print('No instruments found. Exiting script.')
exit()
elif numFound.value == 1:
print('One device found.')
print('Device type: {}'.format(deviceType.value))
print('Device serial number: {}'.format(deviceSerial.value))
ret = rsa.DEVICE_Connect(deviceIDs[0])
if ret != 0:
print('Error in Connect: ' + str(ret))
exit()
else:
print('Unexpected number of devices found, exiting script.')
exit()
I am not quite sure what's going here. Based on the explanation on python
>
os.W_OK:
Value to include in the mode parameter of access() to test the writability of path.
I suppose this check should return True, even if a file does not exist, but its path is valid and I have the permission to write this file.
But this is what happens when I try to check whether a file path is writeable.
import os, subprocess
pwd = os.getcwd();
temp_file_to_write = os.path.join( pwd, "temp_file" );
# use os.access to check
say = "";
if ( os.access( temp_file_to_write, os.W_OK ) ) :
say = "writeable";
else :
say = "NOT writeable";
print "L10", temp_file_to_write, "is", say
# use try/except
try :
with open( temp_file_to_write, "w" ) as F :
F.write( "L14 I am a temp file which is said " + say + "\n" );
print "L15", temp_file_to_write, "is written";
print subprocess.check_output( ['cat', temp_file_to_write ] );
except Exception, e:
print "L18", temp_file_to_write, "is NOT writeable";
It produces the following results
L10 /home/rex/python_code/sandbox/temp_file is NOT writeable
L15 /home/rex/python_code/sandbox/temp_file is written
L14 I am a temp file which is said NOT writeable
Does anyone know why? If my understanding of os.W_OK is wrong, could you tell me the right way in python to check the following both things together 1) whether a file path is valid; and 2) whether I have permissions to write.
Whether or not you can create a new file depends what permissions the directory has, not the new non-existent (yet) file.
Once the file is created (exists) then access(W_OK) may return true if you can modify its content.
Maybe you run your script with sudo (or something like this on Windows)?
I have this on linux (I gave chmod 400):
>>> os.access(fn, os.W_OK)
False
>>> f = open(fn, 'w')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 13] Permission denied: '/tmp/non-writable'
The original question asked how to check permissions to write a file. However, in Python it is better to use a try-except block to attempt to write to a file, instead of testing for access, when possible. The reason is given in the os.access() documentation on the Python.org website: https://docs.python.org/3/library/os.html
From the website:
Note: Using access() to check if a user is authorized to e.g. open a file before
actually doing so using open() creates a security hole, because the user might exploit the short time interval between checking and opening the file to manipulate it. It’s preferable to use EAFP techniques. For example:
if os.access("myfile", os.R_OK):
with open("myfile") as fp:
return fp.read()
return "some default data"
is better written as:
try:
fp = open("myfile")
except PermissionError:
return "some default data"
else:
with fp:
return fp.read()
Note: I/O operations may fail even when access() indicates that they would succeed, particularly for operations on network filesystems which may have permissions semantics beyond the usual POSIX permission-bit model.
I took the following python recipe from Activestate.org, then I simply added the method for deleting the key, however I getting error 5, access denied, and the key it's only a fake key which I have just created to try out the function . Here 's the code
## {{{ http://code.activestate.com/recipes/576860/ (r2)
import win32api
import win32con
def regquerysubkeys(handle, key, keylist=[]):
#get registry handle
reghandle = win32api.RegOpenKeyEx(handle, key, 0, win32con.KEY_ALL_ACCESS)
try:
i = 0
#enumerates subkeys and recursively calls this function again
while True:
subkey = win32api.RegEnumKey(reghandle, i)
#the following is the line I added myself
win32api.RegDeleteKey(handle, key)
i += 1
#braintwister here ;-)
regquerysubkeys(handle, key + subkey + "\\", keylist)
except win32api.error as ex:
#If no more subkeys can be found, we can append ourself
if ex[0] == 259:
keylist.append(key)
#unexpected exception is raised
else:
raise
finally:
#do some cleanup and close the handle
win32api.RegCloseKey(reghandle)
#returns the generated list
print keylist
#call to the function
regquerysubkeys(win32con.HKEY_LOCAL_MACHINE, "SOFTWARE\\suga\\")
Those are the errors I m getting in the console.
Traceback (most recent call last):
File "C:\EclipseWorkspaces\csse120\MMS-auto\test1.py", line 34, in <module>
regquerysubkeys(win32con.HKEY_LOCAL_MACHINE, "SOFTWARE\\suga\\")
File "C:\EclipseWorkspaces\csse120\MMS-auto\test1.py", line 14, in regquerysubkeys
win32api.RegDeleteKey(handle, key)
pywintypes.error: (5, 'RegDeleteKey', 'Access is denied.')
Can anyone help out with it?
Are you running 64-bit Windows 7 by any chance? There were some changes in the structure of the registry to account for running both 32-bit and 64-bit programs that require that you use different APIs for deletion. The RegDeleteKey Win32 API documentation mentions using RegDeleteKeyEx in some cases. The Win32 API is difficult to use reliably from one major version of Windows to the next. Unfortunately, pywin32 does its best to hide a number of the headaches, but it still requires that you really know the Win32 API and its caveats before you can effectively use it.