Detect if Python script is running in focus [duplicate] - python

I would like to get the active window on the screen using python.
For example, the management interface of the router where you enter the username and password as admin
That admin interface is what I want to capture using python to automate the entry of username and password.
What imports would I require in order to do this?

On windows, you can use the python for windows extensions (http://sourceforge.net/projects/pywin32/):
from win32gui import GetWindowText, GetForegroundWindow
print GetWindowText(GetForegroundWindow())
Below code is for python 3:
from win32gui import GetWindowText, GetForegroundWindow
print(GetWindowText(GetForegroundWindow()))
(Found this on http://scott.sherrillmix.com/blog/programmer/active-window-logger/)

Thanks goes to the answer by Nuno André, who showed how to use ctypes to interact with Windows APIs. I have written an example implementation using his hints.
The ctypes library is included with Python since v2.5, which means that almost every user has it. And it's a way cleaner interface than old and dead libraries like win32gui (last updated in 2017 as of this writing). ((Update in late 2020: The dead win32gui library has come back to life with a rename to pywin32, so if you want a maintained library, it's now a valid option again. But that library is 6% slower than my code.))
Documentation is here: https://docs.python.org/3/library/ctypes.html (You must read its usage help if you wanna write your own code, otherwise you can cause segmentation fault crashes, hehe.)
Basically, ctypes includes bindings for the most common Windows DLLs. Here is how you can retrieve the title of the foreground window in pure Python, with no external libraries needed! Just the built-in ctypes! :-)
The coolest thing about ctypes is that you can Google any Windows API for anything you need, and if you want to use it, you can do it via ctypes!
Python 3 Code:
from typing import Optional
from ctypes import wintypes, windll, create_unicode_buffer
def getForegroundWindowTitle() -> Optional[str]:
hWnd = windll.user32.GetForegroundWindow()
length = windll.user32.GetWindowTextLengthW(hWnd)
buf = create_unicode_buffer(length + 1)
windll.user32.GetWindowTextW(hWnd, buf, length + 1)
# 1-liner alternative: return buf.value if buf.value else None
if buf.value:
return buf.value
else:
return None
Performance is extremely good: 0.01 MILLISECONDS on my computer (0.00001 seconds).
Will also work on Python 2 with very minor changes. If you're on Python 2, I think you only have to remove the type annotations (from typing import Optional and -> Optional[str]). :-)
Enjoy!
Win32 Technical Explanations:
The length variable is the length of the actual text in UTF-16 (Windows Wide "Unicode") CHARACTERS. (It is NOT the number of BYTES.) We have to add + 1 to add room for the null terminator at the end of C-style strings. If we don't do that, we would not have enough space in the buffer to fit the final real character of the actual text, and Windows would truncate the returned string (it does that to ensure that it fits the super important final string Null-terminator).
The create_unicode_buffer function allocates room for that many UTF-16 CHARACTERS.
Most (or all? always read Microsoft's MSDN docs!) Windows APIs related to Unicode text take the buffer length as CHARACTERS, NOT as bytes.
Also look closely at the function calls. Some end in W (such as GetWindowTextLengthW). This stands for "Wide string", which is the Windows name for Unicode strings. It's very important that you do those W calls to get proper Unicode strings (with international character support).
PS: Windows has been using Unicode for a long time. I know for a fact that Windows 10 is fully Unicode and only wants the W function calls. I don't know the exact cutoff date when older versions of Windows used other multi-byte string formats, but I think it was before Windows Vista, and who cares? Old Windows versions (even 7 and 8.1) are dead and unsupported by Microsoft.
Again... enjoy! :-)
UPDATE in Late 2020, Benchmark vs the pywin32 library:
import time
import win32ui
from typing import Optional
from ctypes import wintypes, windll, create_unicode_buffer
def getForegroundWindowTitle() -> Optional[str]:
hWnd = windll.user32.GetForegroundWindow()
length = windll.user32.GetWindowTextLengthW(hWnd)
buf = create_unicode_buffer(length + 1)
windll.user32.GetWindowTextW(hWnd, buf, length + 1)
return buf.value if buf.value else None
def getForegroundWindowTitle_Win32UI() -> Optional[str]:
# WARNING: This code sometimes throws an exception saying
# "win32ui.error: No window is is in the foreground."
# which is total nonsense. My function doesn't fail that way.
return win32ui.GetForegroundWindow().GetWindowText()
iterations = 1_000_000
start_time = time.time()
for x in range(iterations):
foo = getForegroundWindowTitle()
elapsed1 = time.time() - start_time
print("Elapsed 1:", elapsed1, "seconds")
start_time = time.time()
for x in range(iterations):
foo = getForegroundWindowTitle_Win32UI()
elapsed2 = time.time() - start_time
print("Elapsed 2:", elapsed2, "seconds")
win32ui_pct_slower = ((elapsed2 / elapsed1) - 1) * 100
print("Win32UI library is", win32ui_pct_slower, "percent slower.")
Typical result after doing multiple runs on an AMD Ryzen 3900x:
My function: 4.5769994258880615 seconds
Win32UI library: 4.8619983196258545 seconds
Win32UI library is 6.226762715455125 percent slower.
However, the difference is small, so you may want to use the library now that it has come back to life (it had previously been dead since 2017). But you're going to have to deal with that library's weird "no window is in the foreground" exception, which my code doesn't suffer from (see the code comments in the benchmark code).
Either way... enjoy!

The following script should work on Linux, Windows and Mac. It is currently only tested on Linux (Ubuntu Mate Ubuntu 15.10).
Prerequisites
For Linux:
Install wnck (sudo apt-get install python-wnck on Ubuntu, see libwnck.)
For Windows:
Make sure win32gui is available
For Mac:
Make sure AppKit is available
The script
#!/usr/bin/env python
"""Find the currently active window."""
import logging
import sys
logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s',
level=logging.DEBUG,
stream=sys.stdout)
def get_active_window():
"""
Get the currently active window.
Returns
-------
string :
Name of the currently active window.
"""
import sys
active_window_name = None
if sys.platform in ['linux', 'linux2']:
# Alternatives: https://unix.stackexchange.com/q/38867/4784
try:
import wnck
except ImportError:
logging.info("wnck not installed")
wnck = None
if wnck is not None:
screen = wnck.screen_get_default()
screen.force_update()
window = screen.get_active_window()
if window is not None:
pid = window.get_pid()
with open("/proc/{pid}/cmdline".format(pid=pid)) as f:
active_window_name = f.read()
else:
try:
from gi.repository import Gtk, Wnck
gi = "Installed"
except ImportError:
logging.info("gi.repository not installed")
gi = None
if gi is not None:
Gtk.init([]) # necessary if not using a Gtk.main() loop
screen = Wnck.Screen.get_default()
screen.force_update() # recommended per Wnck documentation
active_window = screen.get_active_window()
pid = active_window.get_pid()
with open("/proc/{pid}/cmdline".format(pid=pid)) as f:
active_window_name = f.read()
elif sys.platform in ['Windows', 'win32', 'cygwin']:
# https://stackoverflow.com/a/608814/562769
import win32gui
window = win32gui.GetForegroundWindow()
active_window_name = win32gui.GetWindowText(window)
elif sys.platform in ['Mac', 'darwin', 'os2', 'os2emx']:
# https://stackoverflow.com/a/373310/562769
from AppKit import NSWorkspace
active_window_name = (NSWorkspace.sharedWorkspace()
.activeApplication()['NSApplicationName'])
else:
print("sys.platform={platform} is unknown. Please report."
.format(platform=sys.platform))
print(sys.version)
return active_window_name
print("Active window: %s" % str(get_active_window()))

For Linux users:
All the answers provided required additional modules like "wx" that had numerous errors installing ("pip" failed on build), but I was able to modify this solution quite easily -> original source. There were bugs in the original (Python TypeError on regex)
import sys
import os
import subprocess
import re
def get_active_window_title():
root = subprocess.Popen(['xprop', '-root', '_NET_ACTIVE_WINDOW'], stdout=subprocess.PIPE)
stdout, stderr = root.communicate()
m = re.search(b'^_NET_ACTIVE_WINDOW.* ([\w]+)$', stdout)
if m != None:
window_id = m.group(1)
window = subprocess.Popen(['xprop', '-id', window_id, 'WM_NAME'], stdout=subprocess.PIPE)
stdout, stderr = window.communicate()
else:
return None
match = re.match(b"WM_NAME\(\w+\) = (?P<name>.+)$", stdout)
if match != None:
return match.group("name").strip(b'"')
return None
if __name__ == "__main__":
print(get_active_window_title())
The advantage is it works without additional modules. If you want it to work across multiple platforms, it's just a matter of changing the command and regex strings to get the data you want based on the platform (with the standard if/else platform detection shown above sys.platform).
On a side note: import wnck only works with python2.x when installed with "sudo apt-get install python-wnck", since I was using python3.x the only option was pypie which I have not tested. Hope this helps someone else.

There's really no need to import any external dependency for tasks like this. Python comes with a pretty neat foreign function interface - ctypes, which allows for calling C shared libraries natively. It even includes specific bindings for the most common Win32 DLLs.
E.g. to get the PID of the foregorund window:
import ctypes
from ctypes import wintypes
user32 = ctypes.windll.user32
h_wnd = user32.GetForegroundWindow()
pid = wintypes.DWORD()
user32.GetWindowThreadProcessId(h_wnd, ctypes.byref(pid))
print(pid.value)

In Linux under X11:
xdo_window_id = os.popen('xdotool getactivewindow').read()
print('xdo_window_id:', xdo_window_id)
will print the active window ID in decimal format:
xdo_window_id: 67113707
Note xdotool must be installed first:
sudo apt install xdotool
Note wmctrl uses hexadecimal format for window ID.

This only works on windows
import win32gui
import win32process
def get_active_executable_name():
try:
process_id = win32process.GetWindowThreadProcessId(
win32gui.GetForegroundWindow()
)
return ".".join(psutil.Process(process_id[-1]).name().split(".")[:-1])
except Exception as exception:
return None
I'll recommend checking out this answer for making it work on linux, mac and windows.

I'd been facing same problem with linux interface (Lubuntu 20).
What I do is using wmctrl and execute it with shell command from python.
First, Install wmctrl
sudo apt install wmctrl
Then, Add this code :
import os
os.system('wmctrl -a "Mozilla Firefox"')
ref wmctrl :
https://askubuntu.com/questions/21262/shell-command-to-bring-a-program-window-in-front-of-another

In Linux:
If you already have installed xdotool, you can just use:
from subprocess import run
def get__focused_window():
return run(['xdotool', 'getwindowfocus', 'getwindowpid', 'getwindowname'], capture_output=True).stdout.decode('utf-8').split()
While I was writing this answer I've realised that there were also:
A reference about "xdotool" on comments
& another slightly similar "xdotool" answer
So, I've decided to mention them here, too.

Just wanted to add in case it helps, I have a function for my program (It's a software for my PC's lighting I have this simple few line function:
def isRunning(process_name):
foregroundWindow = GetWindowText(GetForegroundWindow())
return process_name in foregroundWindow

Try using wxPython:
import wx
wx.GetActiveWindow()

Related

How I can get DrawingArea window handle in Gtk3?

I get this code on CEF Python 3 (link)
...
self.container = gtk.DrawingArea()
self.container.set_property('can-focus', True)
self.container.connect('size-allocate', self.OnSize)
self.container.show()
...
windowID = self.container.get_window().handle
windowInfo = cefpython.WindowInfo()
windowInfo.SetAsChild(windowID)
self.browser = cefpython.CreateBrowserSync(windowInfo,
browserSettings={},
navigateUrl=GetApplicationPath('example.html'))
...
This code [self.container.get_window().handle] don't work with PyGI and GTK3.
I trying port the code from GTK2 to GTK3, how I can do this?
Edited:
After some search, I found a tip to make get_window work: I call: self.container.realize() before self.container.get_window(). But I cant't get Window Handle yet.
I need put CEF3 window inside a DrawingArea or any element. How I can do this with PyGI?
Edited:
My environment is:
Windows 7
Python 2.7 and Python 3.2
Sadly there seems to be no progress on the python gobject introspection to fix this and make gdk_win32_window_get_handle available (reported a bug in the gnome bugtracker quite a while ago) - it is also quite needed for Python GStreamer and Windows ...
So I followed the suggestion of totaam and used ctypes to access gdk_win32_window_get_handle. Took me forever since I had no experience with this - and well it is somehow quite an ugly hack - but well when needed...
Here is the code:
Gdk.threads_enter()
#get the gdk window and the corresponding c gpointer
drawingareawnd = drawingarea.get_property("window")
#make sure to call ensure_native before e.g. on realize
if not drawingareawnd.has_native():
print("Your window is gonna freeze as soon as you move or resize it...")
ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p
ctypes.pythonapi.PyCapsule_GetPointer.argtypes = [ctypes.py_object]
drawingarea_gpointer = ctypes.pythonapi.PyCapsule_GetPointer(drawingareawnd.__gpointer__, None)
#get the win32 handle
gdkdll = ctypes.CDLL ("libgdk-3-0.dll")
hnd = gdkdll.gdk_win32_window_get_handle(drawingarea_gpointer)
#do what you want with it ... I pass it to a gstreamer videosink
Gdk.threads_leave()
You must first import GdkX11 for get_xid() to be available on the returned GdkX11Window.
from gi.repository import GdkX11
...
-windowID = self.container.get_window().handle
+windowID = self.container.get_window().get_xid()
The answer advising you to use .handle or .get_xid() works on GTK2, but not with GTK3 or on MS Windows, which are part of your question.
I've done a lot of digging and found that there is a function in GTK3 which does what you want: gdk_win32_window_get_handle, but sadly it is not available in the gi bindings.
You may be able to get to it using ctypes or Cython (which is what I am going to do).

Python - How to get the start/base address of a process?

How do I get the start/base address of a process? Per example Solitaire.exe (solitaire.exe+BAFA8)
#-*- coding: utf-8 -*-
import ctypes, win32ui, win32process
PROCESS_ALL_ACCESS = 0x1F0FFF
HWND = win32ui.FindWindow(None,u"Solitär").GetSafeHwnd()
PID = win32process.GetWindowThreadProcessId(HWND)[1]
PROCESS = ctypes.windll.kernel32.OpenProcess(PROCESS_ALL_ACCESS,False,PID)
print PID, HWND,PROCESS
I would like to calculate a memory address and for this way I need the base address of solitaire.exe.
Here's a picture of what I mean:
I think the handle returned by GetModuleHandle is actually the base address of the given module. You get the handle of the exe by passing NULL.
Install pydbg
Source: https://github.com/OpenRCE/pydbg
Unofficial binaries here: http://www.lfd.uci.edu/~gohlke/pythonlibs/#pydbg
from pydbg import *
from pydbg.defines import *
import struct
dbg = pydbg()
path_exe = "C:\\windows\\system32\\calc.exe"
dbg.load(path_exe, "-u amir")
dbg.debug_event_loop()
parameter_addr = dbg.context.Esp #(+ 0x8)
print 'ESP (address) ',parameter_addr
#attach not working under Win7 for me
#pid = raw_input("Enter PID:")
#print 'PID entered %i'%int(pid)
#dbg.attach(int(pid)) #attaching to running process not working
You might want to have a look at PaiMei, although it's not very active right now https://github.com/OpenRCE/paimei
I couldn't get attach() to work and used load instead. Pydbg has loads of functionality, such as read_proccess_memory, write_process_memory etc.
Note that you can't randomly change memory, because an operating system protects memory of other processes from your process (protected mode). Before the x86 processors there were some which allowed all processors to run in real mode, i.e. the full access of memory for every programm. Non-malicious software usually (always?) doesn't read/write other processes' memory.
The HMDOULE value of GetModuleHandle is the base address of the loaded module and is probably the address you need to compute the offset.
If not, that address is the start of the header of the module (DLL/EXE), which can be displayed with the dumpbin utility that comes with Visual Studio or you can interpret it yourself using the Microsoft PE and COFF Specification to determine the AddressOfEntryPoint and BaseOfCode as offsets from the base address. If the base address of the module isn't what you need, one of these two is another option.
Example:
>>> BaseAddress = win32api.GetModuleHandle(None) + 0xBAFA8
>>> print '{:08X}'.format(BaseAddress)
1D0BAFA8
If The AddressOfEntryPoint or BaseOfCode is needed, you'll have to use ctypes to call ReadProcessMemory following the PE specification to locate the offsets, or just use dumpbin /headers solitaire.exe to learn the offsets.
You can use frida to easy do that.
It is very useful to make hack and do some memory operation just like make address offset, read memory, write something to special memory etc...
https://github.com/frida/frida
2021.08.01 update:
Thanks for #Simas Joneliunas reminding
There some step using frida(windows):
Install frida by pip
pip install frida-tools # CLI tools
pip install frida # Python bindings
Using frida api
session = frida.attach(processName)
script = session.create_script("""yourScript""")
script.load()
sys.stdin.read() #make program always alive
session.detach()
Edit your scrip(using JavaScrip)
var baseAddr = Module.findBaseAddress('solitaire.exe');
var firstPointer = baseAddr.add(0xBAFA8).readPointer();
var secondPointer = firstPointer.add(0x50).readPointer();
var thirdPointer = secondPointer.add(0x14).readPointer();
#if your target pointer points to a Ansi String, you can use #thirdPointer.readAnsiString() to read
The official site https://frida.re/

In Python, how do I check if a drive exists w/o throwing an error for removable drives?

Here's what I have so far:
import os.path as op
for d in map(chr, range(98, 123)): #drives b-z
if not op.isdir(d + ':/'): continue
The problem is that it pops up a "No Disk" error box in Windows:
maya.exe - No Disk: There is no disk in
the drive. Please insert a disk into
drive \Device\Harddisk1\DR1 [Cancel, Try Again, Continue]
I can't catch the exception because it doesn't actually throw a Python error.
Apparently, this only happens on removable drives where there is a letter assigned, but no drive inserted.
Is there a way to get around this issue without specifically telling the script which drives to skip?
In my scenario, I'm at the school labs where the drive letters change depending on which lab computer I'm at. Also, I have zero security privileges to access disk management.
Use the ctypes package to access the GetLogicalDrives function. This does not require external libraries such as pywin32, so it's portable, although it is a little clunkier to work with. For example:
import ctypes
import itertools
import os
import string
import platform
def get_available_drives():
if 'Windows' not in platform.system():
return []
drive_bitmask = ctypes.cdll.kernel32.GetLogicalDrives()
return list(itertools.compress(string.ascii_uppercase,
map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1])))
itertools.compress was added in Python 2.7 and 3.1; if you need to support <2.7 or <3.1, here's an implementation of that function:
def compress(data, selectors):
for d, s in zip(data, selectors):
if s:
yield d
Here's a way that works both on Windows and Linux, for both Python 2 and 3:
import platform,os
def hasdrive(letter):
return "Windows" in platform.system() and os.system("vol %s: 2>nul>nul" % (letter)) == 0
If you have the win32file module, you can call GetLogicalDrives():
def does_drive_exist(letter):
import win32file
return (win32file.GetLogicalDrives() >> (ord(letter.upper()) - 65) & 1) != 0
To disable the error popup, you need to set the SEM_FAILCRITICALERRORS Windows error flag using pywin:
old_mode = win32api.SetErrorMode(0)
SEM_FAILCRITICALERRORS = 1 # not provided by PyWin, last I checked
win32api.SetErrorMode(old_mode & 1)
This tells Win32 not to show the retry dialog; when an error happens, it's returned to the application immediately.
Note that this is what Python calls are supposed to do. In principle, Python should be setting this flag for you. Unfortunately, since Python may be embedded in another program, it can't change process-wide flags like that, and Win32 has no way to specify this flag in a way that only affects Python and not the rest of the code.
As long as a little parsing is acceptable, this is one way to do it without installing win32api and without iterating through all possible drive letters.
from subprocess import check_output
def getDriveLetters():
args = [
'wmic',
'logicaldisk',
'get',
'caption,description,providername',
'/format:csv'
]
output = check_output(args)
results = list()
for line in output.split('\n'):
if line:
lineSplit = line.split(',')
if len(lineSplit) == 4 and lineSplit[1][1] == ':':
results.append(lineSplit[1][0])
return results
You could also parse for specific drive types, such as "Network Connection" to get a list of all network mounted drive letters by adding and lineSplit[2] == 'Network Connection' for example.
Alternatively, rather than returning a list, you could return a dictionary, where keys are drive letters and values are unc paths (lineSplit[3]). Or whatever other info you want to pull from wmic. To see more options: wmic logicaldisk get /?
import os
possible_drives_list = [chr(97 + num).upper() for num in range(26)]
for drive in possible_drives_list:
print(drive + ' exists :' + str(os.path.exists(drive + ':\\')))
import os
def IsDriveExists(drive):
return os.path.exists(drive + ':\\')
print(IsDriveExists('c'))
print(IsDriveExists('d'))
print(IsDriveExists('e'))
print(IsDriveExists('x'))
print(IsDriveExists('v'))
this works in any os

Identify Windows Editions

I am writing a function which prints out detailed Windows Version informations, the output may be a tuple like this:
('32bit', 'XP', 'Professional', 'SP3', 'English')
It will be supporting Windows XP and above. And I'm stuck with getting the Windows edition, e.g., "Professional", "Home Basic", etc.
platform.win32_ver() or sys.getwindowsversion() doesn't do it for me.
win32api.GetVersionEx(1) almost hits, but looks like it doesn't tell me enough information.
Then I saw GetProductInfo(), but looks like it's not implemented in pywin32.
Any hints?
You can use ctypes to access any WinAPI function. GetProductInfo() is in windll.kernel32.GetProductInfo.
I'd found a Python version (GPL licensed, but you can see usage of the functions there) of the MSDN "Getting the System Version" example.
If ctypes doesn't work (due to 32 vs 64 bits?), this hack should:
def get_Windows_name():
import subprocess, re
o = subprocess.Popen('systeminfo', stdout=subprocess.PIPE).communicate()[0]
try: o = str(o, "latin-1") # Python 3+
except: pass
return re.search("OS Name:\s*(.*)", o).group(1).strip()
print(get_Windows_name())
Or just read the registry:
try: import winreg
except: import _winreg as winreg
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Windows NT\CurrentVersion") as key:
print(winreg.QueryValueEx(key, "EditionID")[0])
Or use this:
from win32com.client import GetObject
wim = GetObject('winmgmts:')
print([o.Caption for o in wim.ExecQuery("Select * from Win32_OperatingSystem")][0])
I tried a few of the solutions above, but I was looking for something that gave me "Windows XP" or "Windows 7". There are a few more methods in platform that expose even more information.
import platform
print platform.system(),platform.release()

Detect 64bit OS (windows) in Python

Does anyone know how I would go about detected what bit version Windows is under Python. I need to know this as a way of using the right folder for Program Files.
Many thanks
I think the best solution to the problem has been posted by Mark Ribau.
The best answer to the question for Python 2.7 and newer is:
def is_os_64bit():
return platform.machine().endswith('64')
On windows the cross-platform-function platform.machine() internally uses the environmental variables used in Matthew Scoutens answer.
I found the following values:
WinXP-32: x86
Vista-32: x86
Win7-64: AMD64
Debian-32: i686
Debian-64: x86_64
For Python 2.6 and older:
def is_windows_64bit():
if 'PROCESSOR_ARCHITEW6432' in os.environ:
return True
return os.environ['PROCESSOR_ARCHITECTURE'].endswith('64')
To find the Python interpreter bit version I use:
def is_python_64bit():
return (struct.calcsize("P") == 8)
I guess you should look in os.environ['PROGRAMFILES'] for the program files folder.
platform module -- Access to underlying platform’s identifying data
>>> import platform
>>> platform.architecture()
('32bit', 'WindowsPE')
On 64-bit Windows, 32-bit Python returns:
('32bit', 'WindowsPE')
And that means that this answer, even though it has been accepted, is incorrect. Please see some of the answers below for options that may work for different situations.
Came here searching for properly detecting if running on 64bit windows, compiling all the above into something more concise.
Below you will find a function to test if running on 64bit windows, a function to get the 32bit Program Files folder, and a function to get the 64bit Program Files folder; all regardless of running 32bit or 64bit python. When running 32bit python, most things report as if 32bit when running on 64bit, even os.environ['PROGRAMFILES'].
import os
def Is64Windows():
return 'PROGRAMFILES(X86)' in os.environ
def GetProgramFiles32():
if Is64Windows():
return os.environ['PROGRAMFILES(X86)']
else:
return os.environ['PROGRAMFILES']
def GetProgramFiles64():
if Is64Windows():
return os.environ['PROGRAMW6432']
else:
return None
Note: Yes, this is a bit hackish. All other methods that "should just work", do not work when running 32bit Python on 64bit Windows (at least for the various 2.x and 3.x versions I have tried).
Edits:
2011-09-07 - Added a note about why only this hackish method works properly.
def os_platform():
true_platform = os.environ['PROCESSOR_ARCHITECTURE']
try:
true_platform = os.environ["PROCESSOR_ARCHITEW6432"]
except KeyError:
pass
#true_platform not assigned to if this does not exist
return true_platform
http://blogs.msdn.com/b/david.wang/archive/2006/03/26/howto-detect-process-bitness.aspx
Many of these proposed solutions, such as platform.architecture(), fail because their results depend on whether you are running 32-bit or 64-bit Python.
The only reliable method I have found is to check for the existence of os.environ['PROGRAMFILES(X86)'], which is unfortunately hackish.
You should be using environment variables to access this. The program files directory is stored in the environment variable PROGRAMFILES on x86 Windows, the 32-bit program files is directory is stored in the PROGRAMFILES(X86) environment variable, these can be accessed by using os.environ('PROGRAMFILES').
Use sys.getwindowsversion() or the existence of PROGRAMFILES(X86) (if 'PROGRAMFILES(X86)' in os.environ) to determine what version of Windows you are using.
Following this documentation, try this code:
is_64bits = sys.maxsize > 2**32
Im aware that in comments of the question this method was already used.
This is the method the .net framework uses:
import ctypes
def is64_bit_os():
""" Returns wethever system is a 64bit operating system"""
is64bit = ctypes.c_bool()
handle = ctypes.windll.kernel32.GetCurrentProcess() # should be -1, because the current process is currently defined as (HANDLE) -1
success = ctypes.windll.kernel32.IsWow64Process(handle, ctypes.byref(is64bit)) #should return 1
return (success and is64bit).value
print(is64_bit_os())
I just found another way to do this, which may be useful in some situations.
import subprocess
import os
def os_arch():
os_arch = '32-bit'
if os.name == 'nt':
output = subprocess.check_output(['wmic', 'os', 'get', 'OSArchitecture'])
os_arch = output.split()[1]
else:
output = subprocess.check_output(['uname', '-m'])
if 'x86_64' in output:
os_arch = '64-bit'
else:
os_arch = '32-bit'
return os_arch
print 'os_arch=%s' % os_arch()
I tested this code in the following environments:
Ubuntu 16.04 + Python 2.7.12
Mac OS Sierra + Python 2.7.11
Windows 7 Pro 32-bit + Python 2.7.5 (32-bit)
Windows 10 Home 64-bit + Python 2.7.13 (32-bit)
The subject lines asks about detecting 64 or 32bit OS, while the body talks about determining the location of ProgramFiles. The latter has a couple of workable answers here. I'd like to add another solution generalized to handle StartMenu, Desktop, etc. as well as ProgramFiles: How to get path of Start Menu's Programs directory?
When you need to find out things about windows system, it is usually somewhere in the registry, according to MS documentation, you should look at (http://support.microsoft.com/kb/556009) this key value:
HKLM\HARDWARE\DESCRIPTION\System\CentralProcessor\0
and if it is:
0x00000020 (32 in decimal)
It is a 32 bit machine.
64-bit versions of Windows use something called registry redirection and reflection keys. There is a compatibility layer called WoW64 which enables compatibility of 32-bit applications. Starting from Windows 7 and Windows Server 2008 R2 WoW64 registry keys are not longer reflected but shared. You can read about it here:
registry-reflection: msdn.microsoft.com/en-us/library/aa384235(v=vs.85).aspx
affected-keys: msdn.microsoft.com/en-us/library/aa384253(v=vs.85).aspx
wikipedia: en.wikipedia.org/wiki/WoW64
All you need to do is detect existence of those keys. You can use _winreg for that. Use try: and try opening key, example:
try:
aReg = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,"SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run")
import _winreg
def get_registry_value(key, subkey, value):
key = getattr(_winreg, key)
handle = _winreg.OpenKey(key, subkey )
(value, type) = _winreg.QueryValueEx(handle, value)
return value
windowsbit=cputype = get_registry_value(
"HKEY_LOCAL_MACHINE",
"SYSTEM\\CurrentControlSet\Control\\Session Manager\\Environment",
"PROCESSOR_ARCHITECTURE")
print windowsbit
just run this code
if you are working on 64 bit windows machine this will print AMD64
or if you are working on 32 bit it will print AMD32
i hope this code can help to solve this problem fully
This works for me in the Python versions I use: 2.7 and 2.5.4
import win32com.client
import _winreg
shell = win32com.client.Dispatch('WScript.Shell')
proc_arch = shell.ExpandEnvironmentStrings(r'%PROCESSOR_ARCHITECTURE%').lower()
if proc_arch == 'x86':
print "32 bit"
elif proc_arch == 'amd64':
print "64 bit"
else:
raise Exception("Unhandled arch: %s" % proc_arch)
Just to update this old thread - it looks like the platform module reports the correct architecture now (at least, in Python 2.7.8):
c:\python27\python.exe -c "import platform; print platform.architecture(), platform.python_version()"
('32bit', 'WindowsPE') 2.7.6
c:\home\python278-x64\python.exe -c "import platform; print platform.architecture(), platform.python_version()"
('64bit', 'WindowsPE') 2.7.8
(sorry I don't have the rep to comment on the first answer which still claims to be wrong :)
import platform
platform.architecture()[0]
It will return '32bit' or '64bit' depending on system architecture.
The solution posted by Alexander Brüsch is the correct solution, but it has a bug that only reveals itself on python3.x. He neglected to cast the returned value from GetCurrentProcess() to a HANDLE type. Passing a simple integer as the first parameter of IsWow64Process() returns 0 (which is an error flag from win32api). Also, Alexander incorrectly handles the return statement (success has no .value attribute).
For those who stumble on this thread, here is the corrected code:
import ctypes
def is64_bit_os():
"""Returns True if running 32-bit code on 64-bit operating system"""
is64bit = ctypes.c_bool()
handle = ctypes.wintypes.HANDLE(ctypes.windll.kernel32.GetCurrentProcess())
success = ctypes.windll.kernel32.IsWow64Process(handle, ctypes.byref(is64bit))
return success and is64bit.value
print(is64_bit_os())
There is a function named machine in platform module. I installed both Python3.8 32-bit and 64-bit versions on the same 64-bit machine with 64-bit Windows 10 and here is what I found:
And it looks like platform.machine returns machine architecture without bothering what type of python is installed. so here is my
final compilation
import platform
def is_64bit():
return platform.machine().endswith('64')
Most of the answers here are incorrect :/
Here is a simple translation of the well known method used in CMD and this is how microsoft do it too.
import os
_os_bit=64
if os.environ.get('PROCESSOR_ARCHITECTURE').lower() == 'x86' and os.environ.get('PROCESSOR_ARCHITEW6432') is None: _os_bit=32
print(_os_bit)
but remember: Windows 10 on ARM includes an x86-on-ARM64 emulation, so the possible values for PROCESSOR_ARCHITECTURE are: AMD64 or IA64 or ARM64 or x86
A solution, putting together the options from the links below and using os module:
import os
#next save the response from the command prompt saved to a file
window = os.system('PowerShell.exe "gwmi win32_operatingsystem | select osarchitecture" > prompt.txt')
#next read the file
f = open('prompt.txt','r')
windowsos = f.readlines()
f.close()
print(windowsos[3][:-1])
https://datatofish.com/command-prompt-python/
https://www.radishlogic.com/windows/how-to-check-if-your-windows-10-is-64-bit-or-32-bit/
https://www.tutorialspoint.com/how-to-run-a-powershell-script-from-the-command-prompt
import struct
def is64Windows():
return struct.calcsize('P') * 8 == 64
There should be a directory under Windows 64bit, a Folder called \Windows\WinSxS64 for 64 bit, under Windows 32bit, it's WinSxS.

Categories