GetGUIThreadInfo() with pywin32 - python

I am trying to follow this answer and i have reached the point where a should call
GetGUIThreadInfo()
but i cannot find that in the pywin32 docomentation i am using.
What i have done so far is
import win32api
import win32gui
import win32process
test1 = win32gui.FindWindowEx(0, 0, 0, "notepad")
(test1tid, test1pid) = win32process.GetWindowThreadProcessId(test1)
test1hwndFocus = win32process.GetGUIThreadInfo(test1tid)
but the last line is compleatly made up as i cannot find the right way to call the function.
Update1:
Think i made some progress but now my struct just returns 0 when i expect some hwnd... so maybe my struct is not writen to, i think this could be because of the types in my struct, but how do i find the right types?
import win32api
import win32gui
import win32process
import ctypes
class RECT(ctypes.Structure):
_fields_ = [
("left", ctypes.c_ulong),
("top", ctypes.c_ulong),
("right", ctypes.c_ulong),
("bottom", ctypes.c_ulong)
]
class GUITHREADINFO(ctypes.Structure):
_fields_ = [
("cbSize", ctypes.c_ulong),
("flags", ctypes.c_ulong),
("hwndActive", ctypes.c_ulong),
("hwndFocus", ctypes.c_ulong),
("hwndCapture", ctypes.c_ulong),
("hwndMenuOwner", ctypes.c_ulong),
("hwndMoveSize", ctypes.c_ulong),
("hwndCaret", ctypes.c_ulong),
("rcCaret", RECT)
]
guiThreadInfoStruct = GUITHREADINFO()
ctypes.sizeof(gtitest)
test1 = win32gui.FindWindowEx(0, 0, 0, "notepad")
(test1tid, test1pid) = win32process.GetWindowThreadProcessId(test1)
ctypes.windll.user32.GetGUIThreadInfo(test1tid, guiThreadInfoStruct)
print (guiThreadInfoStruct.hwndFocus)
Update2:
I found the types here
update3:
If anyone wanna see what i used this for go look here

Apparently, [MS.Docs]: GetGUIThreadInfo function is not wrapped by PyWin32, so alternative ways must be used. One of them is calling it via [Python 3.Docs]: ctypes - A foreign function library for Python (involves writing a lot of extra code).
code00.py:
#!/usr/bin/env python
import sys
import win32gui as wgui
import win32process as wproc
import win32con as wcon
import ctypes as ct
from ctypes import wintypes as wt
class GUITHREADINFO(ct.Structure):
_fields_ = [
("cbSize", wt.DWORD),
("flags", wt.DWORD),
("hwndActive", wt.HWND),
("hwndFocus", wt.HWND),
("hwndCapture", wt.HWND),
("hwndMenuOwner", wt.HWND),
("hwndMoveSize", wt.HWND),
("hwndCaret", wt.HWND),
("rcCaret", wt.RECT),
]
def __str__(self):
ret = "\n" + self.__repr__()
start_format = "\n {0:s}: "
for field_name, _ in self. _fields_[:-1]:
field_value = getattr(self, field_name)
field_format = start_format + ("0x{1:016X}" if field_value else "{1:}")
ret += field_format.format(field_name, field_value)
rc_caret = getattr(self, self. _fields_[-1][0])
ret += (start_format + "({1:d}, {2:d}, {3:d}, {4:d})").format(self. _fields_[-1][0], rc_caret.top, rc_caret.left, rc_caret.right, rc_caret.bottom)
return ret
def main(*argv):
window_name = "Untitled - Notepad"
hwnd = wgui.FindWindowEx(wcon.NULL, 0, wcon.NULL, window_name)
print("'{0:s}' window handle: 0x{1:016X}".format(window_name, hwnd))
tid, pid = wproc.GetWindowThreadProcessId(hwnd)
print("PId: {0:d}, TId: {1:d}".format(pid, tid))
user32_dll = ct.WinDLL("user32.dll")
GetGUIThreadInfo = getattr(user32_dll, "GetGUIThreadInfo")
GetGUIThreadInfo.argtypes = [wt.DWORD, ct.POINTER(GUITHREADINFO)]
GetGUIThreadInfo.restype = wt.BOOL
gti = GUITHREADINFO()
gti.cbSize = ct.sizeof(GUITHREADINFO)
res = GetGUIThreadInfo(tid, ct.byref(gti))
print("{0:s} returned: {1:d}".format(GetGUIThreadInfo.__name__, res))
if res:
print(gti)
if __name__ == "__main__":
print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
main(*sys.argv[1:])
print("\nDone.")
Output:
e:\Work\Dev\StackOverflow\q059884688>"e:\Work\Dev\VEnvs\py_pc064_03.07.06_test0\Scripts\python.exe" code00.py
Python 3.7.6 (tags/v3.7.6:43364a7ae0, Dec 19 2019, 00:42:30) [MSC v.1916 64 bit (AMD64)] 64bit on win32
'Untitled - Notepad' window handle: 0x00000000042B20D8
PId: 37192, TId: 53072
GetGUIThreadInfo returned: 1
<__main__.GUITHREADINFO object at 0x0000022649436648>
cbSize: 0x0000000000000048
flags: 0
hwndActive: None
hwndFocus: None
hwndCapture: None
hwndMenuOwner: None
hwndMoveSize: None
hwndCaret: None
rcCaret: (0, 0, 0, 0)
Done.
Notes:
print data that you are working with, as it might be different what you'd expect. For example, the Notepad window title is not "notepad" like your code expects it to be, and in that case win32gui.FindWindowEx would return NULL (0).
I also use [ActiveState.Docs]: PyWin32 Documentation (it's old and outdated, but in most cases it's extremely helpful)

Related

How to wrap the SendInput function to python using ctypes

I am trying to get the SendInput function from user32.dll to work in python using ctypes.I am a noob but from what I read from the docs you have to create the structs the function requires in python and then pass it to the function.
import ctypes
import keyboard
from ctypes import *
lib = windll.user32
KEYEVENTF_SCANCODE = 0x8
KEYEVENTF_KEYUP = 0x2
SPACEBAR = 57 # 0x39
INPUT_KEYBOARD = 1
class KEYBDINPUT(Structure):
_fields_ = [('wVk' , c_ushort) , ('wScan' , c_ushort)
, ('dwFlags' , c_ulong) , ('time' , c_ulong) , ('dwExtraInfo' , c_ulong)]
class INPUT(Structure):
_fields_ = [('type' , c_ulong) ,('ki' , KEYBDINPUT)]
lib.SendInput.restype = c_uint
lib.SendInput.argtypes = [c_uint , INPUT , c_int]
keybdinput_obj = KEYBDINPUT(0 , SPACEBAR , KEYEVENTF_SCANCODE , 0 , 0)
input_obj = INPUT(INPUT_KEYBOARD , keybdinput_obj)
keyboard.wait('u')
lib.SendInput(1 , byref(input_obj) , sizeof(INPUT))
keybdinput_obj = KEYBDINPUT(0 , SPACEBAR , KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP , 0 , 0)
input_obj = INPUT(INPUT_KEYBOARD , keybdinput_obj)
lib.SendInput(1 , byref(input_obj) , sizeof(INPUT))
In the microsoft docs at which I guided myself from the INPUT struct had an union but i figured if I would only need the KEYBDINPUT then it's the same thing as if i had an union.
https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-input
https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-keybdinput
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendinput
I pretty much got stuck because i can't see what's going wrong here so I am asking for help.The program is supposed to send a space after i press 'u' on the keyboard (this was for debugging purposes) and i do it this way because i want it to send as a scancode instead of a virtual keypress.
So if there is another way in python with with which you can send scancodes , that'll work and I would appreciate it a lot .
Define the whole union, or at least MOUSEINPUT, which is the largest member of the union. You can test that your definition is the correct size by print(sizeof(INPUT)) and it should agree with printing the size of an INPUT structure in a C program. I got size 28 for 32-bit and 40 for 64-bit C structure.
Also, your second parameter to SendInput is POINTER(INPUT), not INPUT, and ULONG_PTR is not necessarily c_ulong because it depends on running 32-bit or 64-bit Python.
Here's a tested example:
import ctypes
from ctypes import *
from ctypes import wintypes as w
KEYEVENTF_SCANCODE = 0x8
KEYEVENTF_UNICODE = 0x4
KEYEVENTF_KEYUP = 0x2
SPACE = 0x39
INPUT_KEYBOARD = 1
# not defined by wintypes
ULONG_PTR = c_ulong if sizeof(c_void_p) == 4 else c_ulonglong
class KEYBDINPUT(Structure):
_fields_ = [('wVk' ,w.WORD),
('wScan',w.WORD),
('dwFlags',w.DWORD),
('time',w.DWORD),
('dwExtraInfo',ULONG_PTR)]
class MOUSEINPUT(Structure):
_fields_ = [('dx' ,w.LONG),
('dy',w.LONG),
('mouseData',w.DWORD),
('dwFlags',w.DWORD),
('time',w.DWORD),
('dwExtraInfo',ULONG_PTR)]
class HARDWAREINPUT(Structure):
_fields_ = [('uMsg' ,w.DWORD),
('wParamL',w.WORD),
('wParamH',w.WORD)]
class DUMMYUNIONNAME(Union):
_fields_ = [('mi',MOUSEINPUT),
('ki',KEYBDINPUT),
('hi',HARDWAREINPUT)]
class INPUT(Structure):
_anonymous_ = ['u']
_fields_ = [('type',w.DWORD),
('u',DUMMYUNIONNAME)]
print(sizeof(INPUT))
lib = WinDLL('user32')
lib.SendInput.argtypes = w.UINT,POINTER(INPUT),c_int
lib.SendInput.restype = w.UINT
def send_scancode(code):
i = INPUT()
i.type = INPUT_KEYBOARD
i.ki = KEYBDINPUT(0,code,KEYEVENTF_SCANCODE,0,0)
lib.SendInput(1,byref(i),sizeof(INPUT))
i.ki.dwFlags |= KEYEVENTF_KEYUP
lib.SendInput(1,byref(i),sizeof(INPUT))
def send_unicode(s):
i = INPUT()
i.type = INPUT_KEYBOARD
for c in s:
i.ki = KEYBDINPUT(0,ord(c),KEYEVENTF_UNICODE,0,0)
lib.SendInput(1,byref(i),sizeof(INPUT))
i.ki.dwFlags |= KEYEVENTF_KEYUP
lib.SendInput(1,byref(i),sizeof(INPUT))
send_scancode(SPACE)
send_unicode('The quick brown fox jumped over the lazy dog')
Output on terminal running 64-bit Python 3.6:
C:\>example
40
C:\> The quick brown fox jumped over the lazy dog

How to assign value to zero-length array defined by ctypes in Python3

Here I have a class defined like below, whose attribute data is a zero-length array. How to instantiate this class?
class Frame(ctypes.Structure):
_fields_ = [
("id", ctypes.c_uint64),
("size", ctypes.c_uint32),
("data", ctypes.c_byte*0) # zero-length array
]
I tried this
frame = Frame()
frame.id = 0
frame.size = 2
frame.data = ctypes.cast(b'12', ctypes.POINTER(ctypes.c_type * 0))
but an exception was raised at line 4
TypeError: incompatible types, LP_c_byte_Array_0 instance instead of c_byte_Array_0 instance
so, how should I do to instantiate this class correctly?
Listing [Python.Docs]: ctypes - A foreign function library for Python.
This technique (having a struct with a 0 lengthed array as last member) is commonly used in C in order to have variable data right after the struct. Unfortunately, the Python layer doesn't allow that (assigning to an array a value larger than its length). The closest thing to your goal would be to declare the data member as a pointer. Going further, create a setter method that does all conversions:
code00.py:
#!/usr/bin/env python3
import ctypes as ct
import sys
class Frame(ct.Structure):
_fields_ = [
("id", ct.c_uint64),
("size", ct.c_uint32),
("data", ct.POINTER(ct.c_ubyte)), # Make it a pointer
]
def set_data(self, value):
if not isinstance(value, (bytes,)):
raise ValueError("Bytes expected.")
self.data = ct.cast(value, ct.POINTER(ct.c_ubyte))
self.size = len(value)
def main(*argv):
frame = Frame()
frame.set_data(b"123abCD")
for i in range(frame.size):
print("{0:d} - {1:d}".format(i, frame.data[i]))
if __name__ == "__main__":
print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
64 if sys.maxsize > 0x100000000 else 32, sys.platform))
rc = main(*sys.argv[1:])
print("\nDone.")
sys.exit(rc)
Output:
[cfati#CFATI-5510-0:e:\Work\Dev\StackOverflow\q059172596]> "e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" code00.py
Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] 064bit on win32
0 - 49
1 - 50
2 - 51
3 - 97
4 - 98
5 - 67
6 - 68
Done.

How to change folder icons with Python on windows, linux, unix, mac …?

I would like to write a general method for all operating systems (Win, MacOS, Unix, ...) that changes a folder's icon.
I would like to extend the following implementation
import os
import warnings
import ctypes
from ctypes import POINTER, Structure, c_wchar, c_int, sizeof, byref
from ctypes.wintypes import BYTE, WORD, DWORD, LPWSTR, LPSTR
import win32api
class SetFolderIcon(object):
def __init__(self, folderPath, iconPath, reset=False):
assert os.path.isdir(folderPath), "folderPath '%s' is not a valid folder"%folderPath
self.__folderPath = unicode(os.path.abspath(folderPath), 'mbcs')
assert os.path.isfile(iconPath), "iconPath '%s' does not exist"%iconPath
self.__iconPath = unicode(os.path.abspath(iconPath), 'mbcs')
assert isinstance(reset, bool), "reset must be boolean"
self.__reset = reset
# set icon if system is windows
if os.name == 'nt':
try:
self.__set_icon_on_windows()
except Exception as e:
warnings.warn("Unable to set folder icon (%s)"%e)
elif os.name == 'posix':
raise Exception('posix system not implemented yet')
elif os.name == 'mac':
raise Exception('mac system not implemented yet')
elif os.name == 'os2':
raise Exception('os2 system not implemented yet')
elif os.name == 'ce':
raise Exception('ce system not implemented yet')
elif os.name == 'java':
raise Exception('java system not implemented yet')
elif os.name == 'riscos':
raise Exception('riscos system not implemented yet')
def __set_icon_on_windows(self):
HICON = c_int
LPTSTR = LPWSTR
TCHAR = c_wchar
MAX_PATH = 260
FCSM_ICONFILE = 0x00000010
FCS_FORCEWRITE = 0x00000002
SHGFI_ICONLOCATION = 0x000001000
class GUID(Structure):
_fields_ = [ ('Data1', DWORD),
('Data2', WORD),
('Data3', WORD),
('Data4', BYTE * 8) ]
class SHFOLDERCUSTOMSETTINGS(Structure):
_fields_ = [ ('dwSize', DWORD),
('dwMask', DWORD),
('pvid', POINTER(GUID)),
('pszWebViewTemplate', LPTSTR),
('cchWebViewTemplate', DWORD),
('pszWebViewTemplateVersion', LPTSTR),
('pszInfoTip', LPTSTR),
('cchInfoTip', DWORD),
('pclsid', POINTER(GUID)),
('dwFlags', DWORD),
('pszIconFile', LPTSTR),
('cchIconFile', DWORD),
('iIconIndex', c_int),
('pszLogo', LPTSTR),
('cchLogo', DWORD) ]
class SHFILEINFO(Structure):
_fields_ = [ ('hIcon', HICON),
('iIcon', c_int),
('dwAttributes', DWORD),
('szDisplayName', TCHAR * MAX_PATH),
('szTypeName', TCHAR * 80) ]
shell32 = ctypes.windll.shell32
fcs = SHFOLDERCUSTOMSETTINGS()
fcs.dwSize = sizeof(fcs)
fcs.dwMask = FCSM_ICONFILE
fcs.pszIconFile = self.__iconPath
fcs.cchIconFile = 0
fcs.iIconIndex = self.__reset
hr = shell32.SHGetSetFolderCustomSettings(byref(fcs), self.__folderPath, FCS_FORCEWRITE)
if hr:
raise WindowsError(win32api.FormatMessage(hr))
sfi = SHFILEINFO()
hr = shell32.SHGetFileInfoW(self.__folderPath, 0, byref(sfi), sizeof(sfi), SHGFI_ICONLOCATION)
#if hr == 0:
# raise WindowsError(win32api.FormatMessage(hr))
index = shell32.Shell_GetCachedImageIndexW(sfi.szDisplayName, sfi.iIcon, 0)
shell32.SHUpdateImageW(sfi.szDisplayName, sfi.iIcon, 0, index)
iconPath = 'C:\\Users\\myself\\Desktop\\icon.ico'
#iconPath = "C:\\Windows\\system32\\SHELL32.dll"
SetFolderIcon('C:\\Users\\myself\\Desktop\\Newfolder',iconPath, reset=False)
# reset icon
SetFolderIcon('C:\\Users\\myself\\Desktop\\Newfolder',iconPath, reset=True)
As you can see I only implemented the windows version using __set_icon_on_windows method. similar methods such as __set_icon_on_mac ... must be implemented
Thanks

How to use ctypes.windll.Wininet.InternetQueryOptionW in python

several month ago,I wrote https://github.com/325862401/goagent/blob/master/local/ieproxysetting.cpp. that program can set internet proxy automatically.
Now I want to use ctypes.windll.Wininet to do the same thing.
But I donot know how to pass the argument to InternetQueryOptionW.
and I also don't find the class refer to the INTERNET_PER_CONN_OPTION_LIST structure.
is there any demo for the usage of InternetQueryOptionW or InternetSetOptionW in python.
this https://bitbucket.org/canassa/switch-proxy/src/685ac447783a7cb3ead6ce8369b66483790c26be/proxy.py?at=default maybe be helpful.
but I donot want to modify Registry.
just use the api.
Thanks a lot.
sorry for poor English.
Here is Python equivalent to your cpp code, pretty much straight forward conversation (I didn't test it that much):
#-*- coding: utf-8 -*-
#!python
from ctypes import *
from ctypes.wintypes import *
# stick to unicode version
LPWSTR = POINTER(WCHAR)
HINTERNET = LPVOID
INTERNET_PER_CONN_FLAGS = 1
INTERNET_PER_CONN_AUTOCONFIG_URL = 4
INTERNET_PER_CONN_AUTODISCOVERY_FLAGS = 5
INTERNET_OPTION_REFRESH = 37
INTERNET_OPTION_SETTINGS_CHANGED = 39
INTERNET_OPTION_PER_CONNECTION_OPTION = 75
PROXY_TYPE_AUTO_PROXY_URL = 4
class INTERNET_PER_CONN_OPTION(Structure):
class Value(Union):
_fields_ = [
('dwValue', DWORD),
('pszValue', LPWSTR),
('ftValue', FILETIME),
]
_fields_ = [
('dwOption', DWORD),
('Value', Value),
]
class INTERNET_PER_CONN_OPTION_LIST(Structure):
_fields_ = [
('dwSize', DWORD),
('pszConnection', LPWSTR),
('dwOptionCount', DWORD),
('dwOptionError', DWORD),
('pOptions', POINTER(INTERNET_PER_CONN_OPTION)),
]
InternetSetOption = windll.wininet.InternetSetOptionW
InternetSetOption.argtypes = [HINTERNET, DWORD, LPVOID, DWORD]
InternetSetOption.restype = BOOL
if __name__ == '__main__':
proxy = create_unicode_buffer('http://127.0.0.1:8086/proxy.pac')
List = INTERNET_PER_CONN_OPTION_LIST()
Option = (INTERNET_PER_CONN_OPTION * 2)()
nSize = c_ulong(sizeof(INTERNET_PER_CONN_OPTION_LIST))
Option[0].dwOption = INTERNET_PER_CONN_AUTOCONFIG_URL
Option[0].Value.pszValue = proxy
Option[1].dwOption = INTERNET_PER_CONN_FLAGS
Option[1].Value.dwValue = PROXY_TYPE_AUTO_PROXY_URL
List.dwSize = sizeof(INTERNET_PER_CONN_OPTION_LIST)
List.pszConnection = None
List.dwOptionCount = 2
List.dwOptionError = 0
List.pOptions = Option
assert InternetSetOption(None, INTERNET_OPTION_PER_CONNECTION_OPTION, byref(List), nSize) == True
assert InternetSetOption(None, INTERNET_OPTION_SETTINGS_CHANGED, None, 0) == True
assert InternetSetOption(None, INTERNET_OPTION_REFRESH, None, 0) == True
You don't need MultiByteToWideChar, create_unicode_buffer and the unicode version of InternetSetOption should do the job.

Windows WlanApi and Python Ctypes

I'm working on a captive portal projet on Windows. I've written this piece of code (similar to this) :
from ctypes import wintypes
import ctypes
WlanApi = ctypes.windll.wlanapi
hClientHandle = wintypes.HANDLE()
phClientHandle = ctypes.pointer(hClientHandle)
dwNegotiatedVersion = wintypes.DWORD()
pdwNegotiatedVersion = ctypes.pointer(dwNegotiatedVersion)
dwClientVersion = wintypes.DWORD()
dwClientVersion.value = 2L
rc = WlanApi.WlanOpenHandle(dwClientVersion, None, pdwNegotiatedVersion, phClientHandle)
print rc
class GUID(ctypes.Structure):
_fields_ = [("Data1", wintypes.DWORD),
("Data2", wintypes.WORD),
("Data3", wintypes.WORD),
("Data4", wintypes.BYTE * 8)]
class WLAN_INTERFACE_INFO (ctypes.Structure):
_fields_ = [('InterfaceGuid', GUID),
('strInterfaceDescription', wintypes.WCHAR * 256),
('isState', wintypes.????)]
class WLAN_INTERFACE_INFO_LIST(ctypes.Structure):
_fields_ = [('dwNumberOfItems', wintypes.DWORD),
('dwIndex', wintypes.DWORD),
('InterfaceInfo', WLAN_INTERFACE_INFO * 10)]
IfList = WLAN_INTERFACE_INFO_LIST()
pIfList = ctypes.pointer(IfList)
rc = WlanApi.WlanEnumInterfaces(hClientHandle, None, pIfList)
print rc
print "Num Entries: %s" % IfList.dwNumberOfItems
I can't find how to structure "WLAN_INTERFACE_STATE enumeration" and when I try with a WCHAR array or anything else, this script return my 6000000 wireless interfaces !!!
Can somebody help me?
It's just an integer, there is no structure 0 = Not ready, 1 = connected etc.
Hmm it starts to make sense,as most of these structs have a corresponding pointer.
According to the boys at PInvoke
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct WLAN_INTERFACE_INFO
{
/// GUID->_GUID
public Guid InterfaceGuid;
/// WCHAR[256]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string strInterfaceDescription;
/// WLAN_INTERFACE_STATE->_WLAN_INTERFACE_STATE
public WLAN_INTERFACE_STATE isState;
}
Where WLAN_INTERFACE_STATE is
public enum WLAN_INTERFACE_STATE
{
wlan_interface_state_not_ready = 0,
...
// 1 to 6
...
wlan_interface_state_authenticating = 7,
}
PInvoke on WLAN...

Categories

Resources