Use ShellExecuteW
. Your strings are Unicode strings and are passed as wchar_t*
to C.
Alternatively, use byte strings with ShellExecuteA
, e.g. b'open'
and b'PPP.exe'
.
If you fully define the arguments and return type (always recommended), then ctypes
will type-check for you and return an error if the type is incorrect:
import ctypes as ct
from ctypes import wintypes as w
SW_SHOWNORMAL = 1
shell32 = ct.WinDLL('shell32')
shell32.ShellExecuteA.argtypes = w.HWND, w.LPCSTR, w.LPCSTR, w.LPCSTR, w.LPCSTR, w.INT
shell32.ShellExecuteA.restype = w.HINSTANCE
shell32.ShellExecuteW.argtypes = w.HWND, w.LPCWSTR, w.LPCWSTR, w.LPCWSTR, w.LPCWSTR, w.INT
shell32.ShellExecuteW.restype = w.HINSTANCE
# works
shell32.ShellExecuteA(None, b'open', b'cmd.exe', None, None, SW_SHOWNORMAL)
# works
shell32.ShellExecuteW(None, 'open', 'cmd.exe', None, None, SW_SHOWNORMAL)
# ctypes.ArgumentError: argument 2: <class 'TypeError'>: wrong type
shell32.ShellExecuteA(None, 'open', 'cmd.exe', None, None, SW_SHOWNORMAL)
# ctypes.ArgumentError: argument 2: <class 'TypeError'>: wrong type
shell32.ShellExecuteW(None, b'open', b'cmd.exe', None, None, SW_SHOWNORMAL)