I'm writing a Python script to toggle the "Hidden Items" status of the Windows Explorer. It changes the value of Computer\HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Hidden, but for the change to take effect all instances of the Explorer have to be refreshed.
I implemented the same idea a few months ago with AutoHotkey, there I could solve the refresh problem with the following commands I found on the AutoHotkey Forum:
WinGetClass, CabinetWClass
PostMessage, 0x111, 28931, , , A
PostMessage, 0x111, 41504, , , A
I tried different approaches to translate it, but wasn't able to get it working with Python. While searching for an answer I also found a solution with C# (Refresh Windows Explorer in Win7), which is far more complicated than the AutoHotkey version. I could let the Python script call the C# script, but I would much prefer a solution without auxiliary files.
How can I implement such behavior with Python?
Using pywin module:
import win32con
import win32gui
# List for handles:
handles = []
def collect_handles(h, _):
' Get window class name and add it to list '
if win32gui.GetClassName(h) == 'CabinetWClass':
handles.append(h)
def refresh_window(h):
' Send messages to window '
win32gui.PostMessage(h, win32con.WM_COMMAND, 28931, None)
win32gui.PostMessage(h, win32con.WM_COMMAND, 41504, None)
# Fill our list:
win32gui.EnumWindows(collect_handles, None)
# Perform action on our handles:
list(map(refresh_window, handles))
My script runs a command every X seconds.
If a command is like "start www" -> opens a website in a default browser I want to be able to close the browser before next time the command gets executed.
This short part of a script below:
if "start www" in command:
time.sleep(interval - 1)
os.system("Taskkill /IM chrome.exe /F")
I want to be able to support firefox, ie, chrome and opera, and only close the browser that opened by URL.
For that I need to know which process to kill.
How can I use python to identify my os`s default browser in windows?
The solution is going to differ from OS to OS. On Windows, the default browser (i.e. the default handler for the http protocol) can be read from the registry at:
HKEY_CURRENT_USER\Software\Classes\http\shell\open\command\(Default)
Python has a module for dealing with the Windows registry, so you should be able to do:
from _winreg import HKEY_CURRENT_USER, OpenKey, QueryValue
# In Py3, this module is called winreg without the underscore
with OpenKey(HKEY_CURRENT_USER,
r"Software\Classes\http\shell\open\command") as key:
cmd = QueryValue(key, None)
You'll get back a command line string that has a %1 token in it where the URL to be opened should be inserted.
You should probably be using the subprocess module to handle launching the browser; you can retain the browser's process object and kill that exact instance of the browser instead of blindly killing all processes having the same executable name. If I already have my default browser open, I'm going to be pretty cheesed if you just kill it without warning. Of course, some browsers don't support multiple instances; the second instance just passes the URL to the existing process, so you may not be able to kill it anyway.
I would suggest this. Honestly Python should include this in the webbrowser module that unfortunately only does an open bla.html and that breaks anchors on the file:// protocol.
Calling the browser directly however works:
# Setting fallback value
browser_path = shutil.which('open')
osPlatform = platform.system()
if osPlatform == 'Windows':
# Find the default browser by interrogating the registry
try:
from winreg import HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, OpenKey, QueryValueEx
with OpenKey(HKEY_CURRENT_USER, r'SOFTWARE\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice') as regkey:
# Get the user choice
browser_choice = QueryValueEx(regkey, 'ProgId')[0]
with OpenKey(HKEY_CLASSES_ROOT, r'{}\shell\open\command'.format(browser_choice)) as regkey:
# Get the application the user's choice refers to in the application registrations
browser_path_tuple = QueryValueEx(regkey, None)
# This is a bit sketchy and assumes that the path will always be in double quotes
browser_path = browser_path_tuple[0].split('"')[1]
except Exception:
log.error('Failed to look up default browser in system registry. Using fallback value.')
I'm attempting to launch a local html file from python in the default browser (right now my default is Google Chrome if I double-click on a .html file, Chrome launches.)
When I use python's webbrowser.open(), IE launches instead, with a blank address bar.
Python 2.7.1 (r271:86832, Nov 27 2010, 17:19:03) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import webbrowser
>>> filename = 'test.html'
>>> webbrowser.open('file://'+filename)
True
>>> print(webbrowser.get().__class__.__name__)
WindowsDefault
I've checked my default programs and they look correct. I'm on Win 7 SP1. Why is Chrome not launching?
Update: The code will be running on unknown OS's and machines, so hardcoding or registering browsers or path updates are not options. I'm thinking that parsing the url for file:// and then doing an os.path.exists check and os.path.realpath might be the answer.
My main issue was a bad URL by attempting prepend file:// to a relative path. It can be fixed with this:
webbrowser.open('file://' + os.path.realpath(filename))
Using webbrowser.open will try multiple methods until one "succeeds", which is a loose definition.
The WindowsDefault class calls os.startfile() which fails and returns False. I can verify that by entering the URL in the windows run command and seeing an error message rather than a browser.
Both GenericBrowser and BackgroundBrowser will call subprocess.Popen() with an exe which will succeed, even with a bad URL, and return True. IE gives no indication of the issue, all other browsers have a nice messages saying they can't find the file.
GenericBrowser is set by the environment variable BROWSER and is first.
WindowsDefault is second.
BackgroundBrowser is last and includes the fall back IE if nothing else works.
Here is my original setup:
>>> import webbrowser
>>> webbrowser._tryorder
['windows-default',
'C:\\Program Files\\Internet Explorer\\IEXPLORE.EXE']
>>> webbrowser._browsers.items()
[('windows-default', [<class 'webbrowser.WindowsDefault'>, None]),
('c:\\program files\\internet explorer\\iexplore.exe', [None, <webbrowser.BackgroundBrowser object at 0x00000000022E3898>])]
>>>
Here is my setup after modifiying the environment variables:
C:>path=C:\Program Files (x86)\Mozilla Firefox;%path%
C:>set BROWSER=C:\Users\Scott\AppData\Local\Google\Chrome\Application\chrome.exe
C:>python
Python 2.7.1 (r271:86832, Nov 27 2010, 17:19:03) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import webbrowser
>>> webbrowser._tryorder
['C:\\Users\\Scott\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe',
'windows-default',
'firefox',
'C:\\Program Files\\Internet Explorer\\IEXPLORE.EXE']
>>> webbrowser._browsers.items()
[('windows-default', [<class 'webbrowser.WindowsDefault'>, None]),
('c:\\program files\\internet explorer\\iexplore.exe',[None, <webbrowser.BackgroundBrowser object at 0x000000000235E828>]),
('firefox', [None, <webbrowser.BackgroundBrowser object at 0x000000000235E780>]),
('c:\\users\\scott\\appdata\\local\\google\\chrome\\application\\chrome.exe', [None, <webbrowser.GenericBrowser object at 0x000000000235E8D0>])]
>>>
The webbrowser._tryorder gives the list of browsers tried. Registering chrome or adding a BROWSER env var or modifiying my path all would have gotten me the correct browser with a better error message.
Thanks for the help guys, I couldn't have solved this without your ideas.
You can use get(name) to use a specific browser.
You'll need to register the Chrome webbrowser, as it doesn't seem to be one of the predefined browser types, and then you should be able to do this:
webbrowser.get('chrome').open('http://www.google.com')
Update:
Actually, you might be able to just one of the following:
webbrowser.get('windows-default').open('http://www.google.com')
webbrowser.get('macosx').open('http://www.google.com')
The docs show no predefined defaults for Linux.
This opened a new Chrome tab for me, and it's still OS-independent:
webbrowser.get().open('http://www.google.com')
What's odd is that without the get() call, it still uses IE. This looks like a bug with a simple workaround.
Using Windows 10, in short, everything that does not include a full URL in the https://example.com format is opened in IE for me. For example, if I say
webbrowser.open("https://www.example.com")
it will open a new tab in Chrome, while
webbrowser.open("example.com")
will open IE. Any .get() will cause it to not open a browser at all.
Kind of weird behaviour, but I can see that this is a complex thing do implement and likely the OS is to blame for this behavior.
The webbrowser module is supposed to use the default browser, so this might be a bug. On the other hand, use this explanation from the docs to troubleshoot your problem:
If the environment variable BROWSER
exists, it is interpreted to override
the platform default list of browsers,
as a os.pathsep-separated list of
browsers to try in order. When the
value of a list part contains the
string %s, then it is interpreted as a
literal browser command line to be
used with the argument URL substituted
for %s; if the part does not contain
%s, it is simply interpreted as the
name of the browser to launch.
Looking at the module source code, it first tries to use the Windows default browser but if it doesn't work, it searches for common browser names that are commands, ie. that are in the PATH variable. Try adding the location of your web browser to your PATH.
I have the same problem with firefox. http://www.google.com is opened in ff while file:///test.html is opened in IE.
webbrowser doc says:
Note that on some platforms, trying to
open a filename using this function,
may work and start the operating
system’s associated program. However,
this is neither supported nor
portable.
What worked for me with Python 3.6, Windows 10, was using the register() function with BackgroundBrowser, to sign in my desired browser:
import webbrowser
# Register your preferable browser
browser_path = 'C:/path/to/opera.exe'
webbrowser.register('opera', None, webbrowser.BackgroundBrowser(browser_path))
# Get an instance and launch your file
browser = webbrowser.get('opera')
browser.open('html_file')
Bonus observation -
webbrowser also has a GenericBrowser class.
Looking at the source, seems BackgroundBrowser uses start_new_session when calling subprocess.Popen(), whereas GenericBrowser does not.
I'm not aware of that flag's exact functionality.
Practically however, using BackgroundBrowser switches to the browser window, while GenericBrowser just opens the tab, but doesn't switch.
This problem appears for me only with file:/// protocol URLs, which are probably not registered to chrome, so os.startfile() (which is the first thing webbrowser.open tries on Windows) opens them in Internet Explorer. I don't think putting your other browser in the PATH will help, since os.startfile() still gets invoked before even trying the browsers in the path.
What you can do, is to check the default browser for http:// in the registry (for instance, by checking the registry key HKEY_CLASSES_ROOT\http\shell\open\command) and use that one for file:/// URLs. Not pretty, but it should work.
import _winreg
import webbrowser
import shlex
import subprocess
def win_browser_open(url):
if url.startswith('file:///'):
browser = _winreg.QueryValue(_winreg.HKEY_CLASSES_ROOT, r'http\shell\open\command')
browser = browser.replace('%1', url)
subprocess.Popen(shlex.split(browser))
else:
webbrowser.open(url)
Use this:
import webbrowser
webbrowser.get('windows-default').open('http://www.google.com')
since all answers did not solve this/my issue, this way worked for me... (windows)
commands needs to be in a list, not in a single string! (in this case, "start", "filepath"), also shell needs to be True (windows)
import subprocess
subprocess.Popen(['start', 'C:/Users/User/Desktop/convert_report.html'], shell=True)
It seems that webbrowser module couldn't find filename in cwd because you opened the program by shortcut or terminal, so cwd is different from the program's directory.
In that case, you have to convert the path into the absolute path of the program's directory when giving a path to webbrowser.open function.
The program's path is stored as __file__ global constant.
You can fix like that:
webbrowser.open(os.path.join(__file__, '..', filename))
I fixed the same problem by this solution.
Add a BROWSER variable to your system variables and put path of your default browser.
I just had the same issue of web pages suddenly opening with Internet Explorer, which only started after installing Visual Studio 2017. My guess is that VS2017 installed its own version of IE.
My program was opening websites using webbrowser.open(url), but I had stripped the 'https://' protocol from the beginning of each URL. Now, by making sure that all URLs have the 'https://' protocol at the beginning, the issue goes away and the pages are once again opened in Chrome (my Windows default browser).
I have no idea why this won't work....I'm trying to open opera but it says cannot find runnable browser.
op = webbrowser.get('C:\\Program Files\\Opera\\opera.exe')
op.open_new_tab('http://www.stackoverflow.com')
op.open_new_tab('http://www.stackoverflow.com')
The name parameter should just be 'opera':
op = webbrowser.get('opera')
Make sure you have installed Opera on your computer, and that the executable opera.exe is in the path.
>>> import webbrowser
>>> webbrowser.get('opera')
<webbrowser.BackgroundBrowser object at 0x02095490>
See the table of allowed values for the name parameter in the documentation.
If you want to specify the exact path to the executable (which by the way is a bad idea if you want your application to be portable) then you can specify the command line as follows:
op = webbrowser.get(r'C:\\Program Files\\Opera\\opera.exe %s')
As far as I know, you cannot provide a specific filepath for the browser you want to associate with the webbrowser object. You need to just provide one of a few built-in names. The one you want here is "opera" - see http://docs.python.org/py3k/library/webbrowser.html for details.
You should try to set the browser path to BROWSER environment variable.
Here's how to do it in Windows (which you are apparently using):
http://vlaurie.com/computers2/Articles/environment.htm