How can I resolve an error in Targetpath? - python

I am developing a small script that creates a chrome shortcut.
I want to have Facebook as homepage when this shortcut is used so I thought I could just append "www.facebook.com" to the target variable that is fed to shortcut.Targetpath, but I get an error. Here is my code snippet
desktop = winshell.desktop()
path = os.path.join(desktop, "Chrome.lnk")
target = r'C:\Program Files\Google\Chrome\Application\chrome.exe ' '"www.facebook.com'
wDir = r"%ProgramFiles%\Google\Chrome\Application"
icon = r"%ProgramFiles%\Google\Chrome\Application\chrome.exe"
shell = Dispatch('WScript.Shell')
shortcut = shell.CreateShortCut(path)
shortcut.Targetpath = target
shortcut.WorkingDirectory = wDir
shortcut.IconLocation = icon
shortcut.save()
and the IDE shows the following error:
File "C:\Python34\lib\site-packages\win32com\client\dynamic.py", line 581, in __setattr__
raise AttributeError("Property '%s.%s' can not be set." % (self._username_, attr))
AttributeError: Property '<unknown>.Targetpath' can not be set.
How can I fix that?

First of all, Targetpath should contain an executable path, you shouldn't add the default homepage to that variable.
To have Chrome open a default webpage you should use the shortcut.Arguments which is what you're actually missing and you should fix shortcut.TargetPath.
So you should modify your code along the following lines:
target = r'C:\Program Files\Google\Chrome\Application\chrome.exe'
arguments = r'https://www.facebook.com'
and then
shortcut.Targetpath = target
shortcut.Arguments = arguments
In my answer, I assume all the rest is correct. Maybe you will need to modify a bit target and wDir.

Related

pywinauto access a nested submenue

In pywinauto I am trying to access a nested submenue item that contains.
The Path is Datei->Importieren->Vorlagen->comdirect Musterdepot (attached screenshot)
Any idea how I can get this running?
The code I use:
app = Application(backend = 'uia').connect(path = "PortfolioPerformance.exe")
app.Dialog.Anwendungsmenü.item_by_path('Datei->Importieren->Vorlagen->comdirect Musterdepot').click_input()
The error I receive:
AttributeError: 'NoneType' object has no attribute 'is_active'
Screenshot of Menu:
After spending some time I figured out the following behaviour:
Once I expanded the Datei Menu, the print_control_identifiers updated to include the submenues.
The following code will click the correct, but maybe there are nicer solutions out there:
app = Application(backend = 'uia').connect(path = PROCNAME)
dialog = app.dialog
#first open the Importieren submenu:
dialog.Anwendungsmenü.item_by_path('Datei->Importieren')
# then the submenue appears on top level menues, open the importieren menu:
dialog["Importieren"].item_by_path('Vorlagen->comdirect Musterdepot').select()

How to get file's properties from Windows' registry?

I'm trying to get a file type with Python. For example, if I give the code "somearchive.rar" it must return "WinRAR Archive". If I give it "someapplication.exe" it must return "Application", etc...
Basically the text you see when you open a file's properties in Windows, on the "File type" line.
I don't know how to do this, though I think you can do it by looking at the registry or something similar and taking the file's properties (or file's extension properties?) and then keeping only the type, because I saw this code
def def_app(estensione):
class_root = winreg.QueryValue(winreg.HKEY_CLASSES_ROOT, estensione)
with winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, r'{}\shell\open\command'.format(class_root)) as key:
command = winreg.QueryValueEx(key, '')[0]
return shlex.split(command)[0]
that looks at the registry and gives you the default application that opens files with the given extension.
OK, so I found out how to do it... This code checks the file type (or association) by looking in the Windows' registry (the same as opening regedit, going in HKEY_CLASSES_ROOT and then looking at the keys in there, as the user #martineau suggested):
rawcom = os.popen("assoc ."+command[len(command)-1]).read().split("=")
It is already split, so I can do rawcom[1] and get the file type easily.
If there isn't a file association in the Windows' registry, it checks the file type using this code that I found:
def get_file_metadata(path, filename, metadata):
sh = win32com.client.gencache.EnsureDispatch('Shell.Application', 0)
ns = sh.NameSpace(path)
file_metadata = dict()
item = ns.ParseName(str(filename))
for ind, attribute in enumerate(metadata):
attr_value = ns.GetDetailsOf(item, ind)
if attr_value:
file_metadata[attribute] = attr_value
return file_metadata
if __name__ == '__main__':
folder = direc
filename = file
metadata = ['Name', 'Size', 'Item type', 'Date modified', 'Date created']
proprietà = get_file_metadata(folder, filename, metadata)
It does exactly what I was trying to do at the start, getting the file type as if I was opening the file's properties in the Windows explorer. With this I put the file metadata in a dictionary and then get only the "Item type" value.
maybe this library can help: filetype
Example:
In [1]: import filetype
In [2]: kind = filetype.guess('/Users/ayik/Pictures/Archive.rar')
In [3]: print(f'MIME type: {kind.mime}')
MIME type: application/x-rar-compressed
from then you can map the MIME types to your desired types

Getting icon from external applications

I am trying to prepare an application similar to 'Windows Start Menu Search'.
That's why I need each applications own icon.
From the C:\ProgramData\Start Menu\Programs\ file path, I add existing applications to a list (QListWidget) with their names and path.
And I get the icons like this:
https://forum.qt.io/topic/62866/getting-icon-from-external-applications
provider = QFileIconProvider()
info = QFileInfo("program_path")
icon = QIcon(provider.icon(info))
And naturally the result is this:
But I don't want this "shortcut icon" to appear.
Then, I am thinking and I came to this conclusion:
shell = win32com.client.Dispatch("WScript.Shell")
provider = QFileIconProvider()
shortcut = shell.CreateShortCut(programPath)
info = QFileInfo(shortcut.targetPath)
icon = QIcon(provider.icon(info))
This solution worked. But, It has created issue for some applications.
So I am looking for an alternative solution.
You were almost there.
Browsing the menu directory tree is actually the right path, but you also have to ensure that the icon of the link is actually the same of the target, as it might not.
The shortcut.iconlocation is a string representing a "tuple" (sort of) including the icon path and the index (as icon resources might contain more than one icon).
>>> shortcut = shell.createShortCut(linkPath)
>>> print(shortcut.iconlocation)
# most links will return this:
> ",0"
# some might return this:
> ",4"
# or this:
> "C:\SomePath\SomeProgram\SomeExe.exe,5"
As long as the icon index is 0, you can get the icon using QFileIconProvider with the targetPath or iconLocation (if there's something before the comma).
The problem comes when there's a value different from 0 for the icon index, as Qt doesn't handle that.
I've put together a simple function (based on some research here on StackOverflow).
def getIcon(self, shortcut):
iconPath, iconId = shortcut.iconLocation.split(',')
iconId = int(iconId)
if not iconPath:
iconPath = shortcut.targetPath
iconPath = os.path.expandvars(iconPath)
if not iconId:
return QICon(self.iconProvider.icon(QFileInfo(iconPath)))
iconRes = win32gui.ExtractIconEx(iconPath, iconId)
hdc = win32ui.CreateDCFromHandle(win32gui.GetDC(0))
hbmp = win32ui.CreateBitmap()
# I think there's a way to find available icon sizes, I'll leave it up to you
hbmp.CreateCompatibleBitmap(hdc, 32, 32)
hdc = hdc.CreateCompatibleDC()
hdc.SelectObject(hbmp)
hdc.DrawIcon((0, 0), iconRes[0][0])
hdc.DeleteDC()
# the original QtGui.QPixmap.fromWinHBITMAP is now part of the
# QtWin sub-module
return QtGui.QIcon(QtWin.fromWinHBITMAP(hbmp.GetHandle(), 2))

Get Application Name from .exe file in python

I am getting both the currently active window title and exe filepath with the code below
hwnd = win32gui.GetForegroundWindow()
_, pid = win32process.GetWindowThreadProcessId(hwnd)
if hwnd != 0 or pid != 0:
try:
hndl = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ, 0, pid)
self.newExe = win32process.GetModuleFileNameEx(hndl, 0)
self.newWindowTitle = win32gui.GetWindowText(hwnd)
except:
self.newExe = ''
self.newWindowTitle = ''
the issue is that although it often is, the window title is not always the application name (the name the users understand as the main part of an application) and this is what I need. for example from calc.exe get Calculator withiout relying on the window title.
the purpose is to create a script that will log in an xml comparative use of any software on a computer
Is this possible?
Most Windows applications store information such as this inside their resource tables. There are API calls that can be used to extract this.
The following extracts the file description from a given application:
import win32api
def getFileDescription(windows_exe):
try:
language, codepage = win32api.GetFileVersionInfo(windows_exe, '\\VarFileInfo\\Translation')[0]
stringFileInfo = u'\\StringFileInfo\\%04X%04X\\%s' % (language, codepage, "FileDescription")
description = win32api.GetFileVersionInfo(windows_exe, stringFileInfo)
except:
description = "unknown"
return description
print(getFileDescription(r"C:\Program Files\Internet Explorer\iexplore.exe"))
The output is:
Internet Explorer
You could therefore pass the result of your call to win32process.GetModuleFileNameEx() to this function.

Python 2.7 changing default browser for webbrower.open

I am trying to open a page a wrote and saved to a local server. Everything is great but it defaults to opening in IE instead of Chrome. Chrome is my default browser and couldn't find any helpful tips online.
Sample code:
import webbrowser
webbrowser.open('192.168.1.254:1337/SmartFormTest1.php')
Thanks in advance!
Alright, found the issue. My browser was correctly defaulted to chrome, the issue is the webbrowser.py file. Lines 539-563 read:
if sys.platform[:3] == "win":
class WindowsDefault(BaseBrowser):
def open(self, url, new=0, autoraise=True):
try:
os.startfile(url)
except WindowsError:
# [Error 22] No application is associated with the specified
# file for this operation: '<URL>'
return False
else:
return True
_tryorder = []
_browsers = {}
# First try to use the default Windows browser
register("windows-default", WindowsDefault)
# Detect some common Windows browsers, fallback to IE
iexplore = os.path.join(os.environ.get("PROGRAMFILES", "C:\\Program Files"),
"Internet Explorer\\IEXPLORE.EXE")
for browser in ("firefox", "firebird", "seamonkey", "mozilla",
"netscape", "opera", iexplore):
if _iscommand(browser):
register(browser, None, BackgroundBrowser(browse()
All I needed to do was add "chrome" to the list of for browser in (list).
Following the documentation, there are a few directions you can go with this:
Set the environment variable BROWSER
Use webbrowser.get('chrome') to get a controller instance of Chrome, then use that to do your browsing
Check your setup -- are you positive that your default browser is set properly? Does it appear under the "Internet" icon in your Start menu?
In Windows, the following code works for me.
chrome_path = '"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe" %s'
webbrowser.get(chrome_path).open('google.com')
My browser was correctly defaulted to brave, just change it in the webbrowser.py file. Lines 539-563
In Line 540, just change the OS path to the desired browser you want to use. For Brave just change the path given to the iexplorer variable
like this:
iexplore = os.path.join(os.environ.get("PROGRAMFILES", "C:\\Program Files"),
"BraveSoftware\\Brave-Browser\\Application\\brave.EXE")

Categories