Is there an easy way to show the properties dialog for a file in Windows using Python?
I'm trying to show the same window that pops up when you right click a file in Explorer and choose Properties.
The way to do this is to call the Windows ShellExecuteEx() API passing the properties verb. There are various high-level Python wrappers of this but I have not succeeded in getting any of them to work with the properties verb. Instead I would use good old ctypes.
import time
import ctypes
import ctypes.wintypes
SEE_MASK_NOCLOSEPROCESS = 0x00000040
SEE_MASK_INVOKEIDLIST = 0x0000000C
class SHELLEXECUTEINFO(ctypes.Structure):
_fields_ = (
("cbSize",ctypes.wintypes.DWORD),
("fMask",ctypes.c_ulong),
("hwnd",ctypes.wintypes.HANDLE),
("lpVerb",ctypes.c_char_p),
("lpFile",ctypes.c_char_p),
("lpParameters",ctypes.c_char_p),
("lpDirectory",ctypes.c_char_p),
("nShow",ctypes.c_int),
("hInstApp",ctypes.wintypes.HINSTANCE),
("lpIDList",ctypes.c_void_p),
("lpClass",ctypes.c_char_p),
("hKeyClass",ctypes.wintypes.HKEY),
("dwHotKey",ctypes.wintypes.DWORD),
("hIconOrMonitor",ctypes.wintypes.HANDLE),
("hProcess",ctypes.wintypes.HANDLE),
)
ShellExecuteEx = ctypes.windll.shell32.ShellExecuteEx
ShellExecuteEx.restype = ctypes.wintypes.BOOL
sei = SHELLEXECUTEINFO()
sei.cbSize = ctypes.sizeof(sei)
sei.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_INVOKEIDLIST
sei.lpVerb = "properties"
sei.lpFile = "C:\\Desktop\\test.txt"
sei.nShow = 1
ShellExecuteEx(ctypes.byref(sei))
time.sleep(5)
The reason I put in the call to sleep is that the properties dialog is shown as a window in the calling process. If the Python executable terminates immediately following the call to ShellExecuteEx, then there is nothing there to service the dialog and it does not show.
Related
I want to show/hide tabtip.exe on demand. I was able to toggle it using code given to me here.
import win32gui
from ctypes import HRESULT
from ctypes.wintypes import HWND
from comtypes import IUnknown, GUID, COMMETHOD
import comtypes.client
class ITipInvocation(IUnknown):
_iid_ = GUID("{37c994e7-432b-4834-a2f7-dce1f13b834b}")
_methods_ = [
COMMETHOD([], HRESULT, "Toggle",
( ['in'], HWND, "hwndDesktop" )
)
]
dtwin = win32gui.GetDesktopWindow();
ctsdk = comtypes.client.CreateObject("{4ce576fa-83dc-4F88-951c-9d0782b4e376}", interface=ITipInvocation)
ctsdk.Toggle(dtwin);
comtypes.CoUninitialize()
But it toggle the keyboard, I want show and hide functions separate. I am trying to use this method but can't understand how can I implement it in python. Any guide would be appreciated.
Side Note:
I am new to COM and win32Api. I have been reading a lot MSDN documentation and posts on it. But there are very few available regarding these topic. If you know any good tutorial on "Using COM interface in python", it would be grateful.
I have a field in a property browser where the user sets a file path. I would like for them to get a file browser when the click on the line to edit it.
the file browser is
class TargetPropertiesBrowser(QtTreePropertyBrowser):
def __init__(self):
self._variantManager = QtVariantPropertyManager()
general_group = self._variantManager.addProperty(QtVariantPropertyManager.groupTypeId(), "General")
self._outputPath = self._variantManager.addProperty(QVariant.String, Target.OUTPUT_PATH)
self._outputPath.setToolTip("Output Directory")
general_group.addSubProperty(self._outputPath)
Now lets say I have some class PopUpBrowser that defines the popup I want displayed when they click in the property browser on the file path line. I can't find an example or documentation on how to alter the behavior or the QtTreePropertyBrowser.
Edit:
If there is a signal I can connect to for when a user clicks on the line that would be fine, however I don't see such a signal in the docs. I'm also not seeing any Enum for a variant manager (or any alternate managers) that supports a widget or button that could link a widget. Sorry if I was unclear.
Connect one of the Widget's Signals (e.g. clicked()) to a slot method in your class: http://pyqt.sourceforge.net/Docs/PyQt5/signals_slots.html
I am yet to decide what language and tools to use for my next project. I would love to use python, but I would like to implement ribbon toolbars. Some work has been done in Tk (http://www.ellogon.org/petasis/bibliography/Tcl2010/TkRibbon.pdf), but it looks like it hasn't been implemented in tkinter yet. Is there anything I can do to get this to work?
You need to create a wrapper for this and get a version of the binary you can use. I built this for use with Python 3.4 and copied it to tkribbon1.0-x86_64.zip. You should unzip this in the Python/tcl subdirectory so the version of tcl used by python can load it.
A minimal wrapper looks like this:
from tkinter import Widget
from os import path
class Ribbon(Widget):
def __init__(self, master, kw=None):
self.version = master.tk.call('package','require','tkribbon')
self.library = master.tk.eval('set ::tkribbon::library')
Widget.__init__(self, master, 'tkribbon::ribbon', kw=kw)
def load_resource(self, resource_file, resource_name='APPLICATION_RIBBON'):
"""Load the ribbon definition from resources.
Ribbon markup is compiled using the uicc compiler and the resource included
in a dll. Load from the provided file."""
self.tk.call(self._w, 'load_resources', resource_file)
self.tk.call(self._w, 'load_ui', resource_file, resource_name)
if __name__ == '__main__':
import sys
from tkinter import *
def main():
root = Tk()
r = Ribbon(root)
name = 'APPLICATION_RIBBON'
if len(sys.argv) > 1:
resource = sys.argv[1]
if len(sys.argv) > 2:
name = sys.argv[2]
else:
resource = path.join(r.library, 'libtkribbon1.0.dll')
r.load_resource(resource, name)
t = Text(root)
r.grid(sticky=(N,E,S,W))
t.grid(sticky=(N,E,S,W))
root.grid_columnconfigure(0, weight=1)
root.grid_rowconfigure(1, weight=1)
root.mainloop()
main()
Running this uses the resources built-in to the tkribbon dll and looks like . The complicated bit is going to be getting some Ribbon markup resources into a DLL for loading.
You can use this example to load ribbons from existing applications. For instance, python Ribbon.py c:\Windows\System32\mspaint.exe MSPAINT_RIBBON will load up the ribbon resource from mspaint. The resource name in this case has to be included as the default is APPLICATION_RIBBON. For your own ribbon, using uicc to build a .rc file, then rc /r file.rc to produce a .res file and finally link -dll -out:file.dll file.rc -noentry -machine:AMD64 seems to work to produce a resource only DLL that works with this extension.
In my PyQt4 application, there is a functionality that allows users to save a avi file.
To this aim, a saveMovie method has been implemented in the main window:
def saveMovie(self):
""" Let the user make a movie out of the current experiment. """
filename = QtGui.QFileDialog.getSaveFileName(self, "Export Movie", "",
'AVI Movie File (*.avi)')
if filename != "":
dialog = QtGui.QProgressDialog('',
QtCore.QString(),
0, 100,
self,
QtCore.Qt.Dialog |
QtCore.Qt.WindowTitleHint)
dialog.setWindowModality(QtCore.Qt.WindowModal)
dialog.setWindowTitle('Exporting Movie')
dialog.setLabelText('Resampling...')
dialog.show()
make_movie(self.appStatus, filename, dialog)
dialog.close()
My idea is to use a QProgressDialog to show how the video encoding work is proceeding.
Nevertheless, after the selection of the filename, the QFileDialog won't disappear and the entire application stays unresponsive until the make_movie function has completed.
What should I do to avoid this?
Lesson learned: if you have some long-running operations to do -- for example, reading or writing a big file, move them to another thread or they will freeze the UI.
Therefore, I created a subclass of QThread, MovieMaker, whose run method encapsulates the functionality previosly implemented by make_movie:
class MovieMaker(QThread):
def __init__(self, uAppStatus, uFilename):
QtCore.QThread.__init__(self, parent=None)
self.appStatus = uAppStatus
self.filename = uFilename
def run(self):
## make the movie and save it on file
Let's move back to the saveMovie method. Here, I replaced the original call to make_movie with the following code:
self.mm = MovieMaker(self.appStatus,
filename)
self.connect(self.mm, QtCore.SIGNAL("Progress(int)"),
self.updateProgressDialog)
self.mm.start()
Note how I defined a new signal, Progress(int).
Such a signal is emitted by the MovieMaker thread to update the QProgressDialog used to show the user how the movie encoding work is progressing.
I'm implementing a minimal browser in PyObjC for my study.
First, I googled about the way to use webkit from pyobjc and wrote code like below:
#coding: utf-8
import Foundation
import WebKit
import AppKit
import objc
def main():
app = AppKit.NSApplication.sharedApplication()
rect = Foundation.NSMakeRect(100,350,600,800)
win = AppKit.NSWindow.alloc()
win.initWithContentRect_styleMask_backing_defer_(
rect,
AppKit.NSTitledWindowMask |
AppKit.NSClosableWindowMask |
AppKit.NSResizableWindowMask |
AppKit.NSMiniaturizableWindowMask,
AppKit.NSBackingStoreBuffered,
False)
win.display()
win.orderFrontRegardless()
webview = WebKit.WebView.alloc()
webview.initWithFrame_(rect)
pageurl = Foundation.NSURL.URLWithString_("http://twitter.com")
req = Foundation.NSURLRequest.requestWithURL_(pageurl)
webview.mainFrame().loadRequest_(req)
win.setContentView_(webview)
app.run()
if __name__ == '__main__':
main()
It worked fine. But I noticed that this browser is sharing cookies with safari. I want it to be independent from my Safari.app.
So I googled again and I learned that I can override cookie-handling-methods by using NSMutableURLRequest.
Below is the second code I tested:
#coding: utf-8
import Foundation
import WebKit
import AppKit
import objc
def main():
app = AppKit.NSApplication.sharedApplication()
rect = Foundation.NSMakeRect(100,350,600,800)
win = AppKit.NSWindow.alloc()
win.initWithContentRect_styleMask_backing_defer_(
rect,
AppKit.NSTitledWindowMask |
AppKit.NSClosableWindowMask |
AppKit.NSResizableWindowMask |
AppKit.NSMiniaturizableWindowMask,
AppKit.NSBackingStoreBuffered,
False)
win.display()
win.orderFrontRegardless()
webview = WebKit.WebView.alloc()
webview.initWithFrame_(rect)
pageurl = Foundation.NSURL.URLWithString_("http://twitter.com")
req = Foundation.NSMutableURLRequest.requestWithURL_(pageurl)
Foundation.NSMutableURLRequest.setHTTPShouldHandleCookies_(req, False)
webview.mainFrame().loadRequest_(req)
win.setContentView_(webview)
app.run()
if __name__ == '__main__':
main()
This code show me a login screen of twitter :-)
But I couldn't login to twitter by this browser.
I input account name, password and pushed enter key. Then the browser displays the timeline of the account which I always use in Safari.app.
Yes, I know that it's proper result.
I didn't write anything about handling cookies.
And my question is on this point.
I want to know that:
How can I implement and use something like NSHTTPCookieStorage?
Can I write it in python?
Thank you.
To start with the easy part: if it is possible to do this in Objective-C it should also be possible with PyObjC.
That said, it is unclear to me if this is possible at all. How can I have multiple instances of webkit without sharing cookies? seems to indicate that it isn't although you might be able to do something through the webkit delegate.
An other alternative is to use NSURLProtocol, register a custom NSURLProtocol class for handling http/https requests and implement that using Python's urllib or urllib2. The PyDocURL example shows how to do this (that example registers a subclass for pydoc:// URLs).
More information on NSURLConnection is on Apple's website.
Updated with an implemention hint:
An alternate method might be to disable cookie storaga by NSHTTPCookieStorage (NSHTTPCookieStorage.sharedHTTPCookieStorage.setCookieAcceptPolicy_(NSHTTPCookieAcceptPolicyNever)). Then use the webkit resource loading delegate to handle cookies yourself:
Maintain your own cookie store (possibly using a class in urllib2)
In webView:resource:willSendRequest:redirectResponse:fromDataSource: add cookie headers based on information in that store
In webView:resource:didReceiveResponse:fromDataSource: check for "set-cookie" headers and update your own cookie store.
It shouldn't be too hard to do this, and I'd love to have this functionality as an example on the PyObjC website (or even as a utility class in the WebKit bindings for PyObjC).