From qermit at sezamkowa.net Sun May 2 14:37:13 2021 From: qermit at sezamkowa.net (Piotr Miedzik) Date: Sun, 2 May 2021 20:37:13 +0200 Subject: [python-win32] how to access IID_IPropertyStore interface Message-ID: I'm trying to write Jump Lists without PyQt5. In fact I'm rewriting this source https://github.com/qt/qtwinextras/blob/18bee52fe48500bca46de7e47d134940c48b524c/src/winextras/qwinjumplist.cpp#L141 To set title or separator I need to access `IID_IPropertyStore` interface (`{886D8EEB-8CF2-4446-8d02-CDBA1DBDCF99}`) But I cannot find it in pywin32. ``` from win32com.shell import shell import pythoncom jumplist = pythoncom.CoCreateInstance( shell.CLSID_DestinationList, None, pythoncom.CLSCTX_INPROC_SERVER, shell.IID_ICustomDestinationList) jumplist.BeginList() collection = pythoncom.CoCreateInstance( shell.CLSID_EnumerableObjectCollection, None, pythoncom.CLSCTX_INPROC_SERVER, shell.IID_IObjectCollection) link = pythoncom.CoCreateInstance( shell.CLSID_ShellLink, None, pythoncom.CLSCTX_INPROC_SERVER, shell.IID_IShellLinkW) link.SetDescription("Test description") link.SetPath("C:\\Windows\\System32\\cmd.exe") # link.SetIconLocation("C:\\Windows\\System32\\cmd.exe", 0) collection.AddObject(link) # jumplist.AppendCategory("Test", collection) jumplist.AddUserTasks(collection) jumplist.CommitList() ``` It gives me error when I'm executing `AddUserTasks` ``` python.exe cleaner.py Traceback (most recent call last): File "cleaner.py", line 25, in jumplist.AddUserTasks(collection) pywintypes.com_error: (-2147024809, 'The parameter is incorrect.', None, None) ``` Is there a way to generate missing interface? -- Piotr Miedzik From skippy.hammond at gmail.com Sun May 2 23:34:23 2021 From: skippy.hammond at gmail.com (Mark Hammond) Date: Mon, 3 May 2021 13:34:23 +1000 Subject: [python-win32] how to access IID_IPropertyStore interface In-Reply-To: References: Message-ID: <9cbbc27a-932e-8b3d-4f25-d74dd4847800@gmail.com> On 3/05/2021 4:37 am, Piotr Miedzik wrote: > I'm trying to write Jump Lists without PyQt5. In fact I'm rewriting > this source https://github.com/qt/qtwinextras/blob/18bee52fe48500bca46de7e47d134940c48b524c/src/winextras/qwinjumplist.cpp#L141 > > To set title or separator I need to access `IID_IPropertyStore` > interface (`{886D8EEB-8CF2-4446-8d02-CDBA1DBDCF99}`) This is in the win32com.propsys.propsys module: >>> from win32com.propsys import propsys >>> propsys.IID_IPropertyStore IID('{886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99}') Cheers, Mark From ernst at pleiszenburg.de Wed May 12 07:00:24 2021 From: ernst at pleiszenburg.de (Sebastian M. Ernst) Date: Wed, 12 May 2021 13:00:24 +0200 Subject: [python-win32] Inheriting a command line - or how to efficiently replace Unix' os.execvpe Message-ID: Hi all, I am dealing with a Python script line - which does, after some preparation work, launch `ssh` (Windows 10 does have native `OpenSSH` now). My script is actually a small CLI tool. On Unix-like systems, at the end of its life, the Python script replaces itself with the `ssh` client, so the user can now interact with `ssh` directly (i.e. run arbitrary commands on the remote machine etc): `os.execvpe('ssh', ['ssh', '-o', 'foo', 'user at host'], os.environ)` `os.execvpe` is present in the Python standard library on Windows, but it does not replace the original (Python) process. Windows is apparently lacking relevant POSIX semantics. It starts the new process more or less like a child, but does not allow it to control the command line. Instead, both the Python process and the child die. The child merely manages to produce a few lines of output before that. After having poked around in MSDN, I think I can make the child "inherit" the command line, i.e. allow it to control it. However, I am having trouble figuring out how. My most successful bad solution looks as follows (directly using one of `win32`'s examples for simplicity): ```python from win32.Demos.winprocess import Process from shlex import join Process(join(['ssh', '-o', 'foo', 'user at host'])) ``` `ssh` opens into a second, new `cmd.exe` window and can be interacted with. The original `cmd.exe` window with Python in it remains open, Python itself quits, returning control to `cmd.exe` itself. I guess it comes down to configuring `win32process.STARTUPINFO` correctly, but even after heaving read tons of documentation on it, I am somehow failing to make sense of it ... --- Full disclosure: I published this question on SO a while ago and even put a bounty on it. No meaningful reply so far. In case someone wants to earn the points before they're gone ... https://stackoverflow.com/q/67371606/1672565 Best regards, Sebastian From eryksun at gmail.com Wed May 12 19:03:31 2021 From: eryksun at gmail.com (Eryk Sun) Date: Wed, 12 May 2021 18:03:31 -0500 Subject: [python-win32] Inheriting a command line - or how to efficiently replace Unix' os.execvpe In-Reply-To: References: Message-ID: On 5/12/21, Sebastian M. Ernst wrote: > > It starts the new process more or less like a child, but does not allow it to > control the command line. Instead, both the Python process and the child > die. The child merely manages to produce a few lines of output before that. First let's go over some basic information about consoles in Windows. Each console session [1] is implemented by a host process, which currently is either conhost.exe or openconsole.exe (used by Windows Terminal). Each Windows process can attach to one and only one console session at a time. A console session doesn't always have a window (i.e. the CREATE_NO_WINDOW process creation flag). Windows 10 also allows the console host to operate in pseudoconsole mode, which relays I/O to another application that implements the console/terminal user interface, or no UI at all. For example, each tab in Windows Terminal (wt.exe) is a pseudoconsole session that's hosted by an instance of openconsole.exe. A console session doesn't implement the POSIX concept of foreground and background process groups. Any process that's attached to a console can read and write from it. Generally when one starts a child process in the same console session, one either avoids using console I/O until the child exits, or one simply blocks and does nothing while waiting for the child to exit. Typically a command-line shell (e.g. cmd.exe) implements the latter. > `os.execvpe` is present in the Python standard library on Windows, but > it does not replace the original (Python) process. Windows is apparently > lacking relevant POSIX semantics. os.execve() is implemented internally as the equivalent of os.spawnve() with P_OVERLAY. I suggest you pretend that it does not exist. Windows does not support overlaying a new executable image on the current process, which is what callers reasonably expect from an exec() call. Instead, with P_OVERLAY the parent process spawns the child in a new process and then exits. If a grandparent process is waiting on the parent process, it will resume when the parent exits. The grandparent and its grandchild will then compete with each other for console I/O, which is an interleaved mess. You'll get a prompt from the grandparent, but the text you enter will be read by the grandchild. Then you'll get the grandchild's prompt, and so on. > `ssh` opens into a second, new `cmd.exe` window and can be interacted > with. The original `cmd.exe` window with Python in it remains open, > Python itself quits, returning control to `cmd.exe` itself. You're confusing things. cmd.exe is just a console client application. It has nothing to do with implementing a console session. If `ssh` is "ssh.bat", then it will execute via cmd.exe. But if it's an executable binary, either it will allocate a new console session if it doesn't inherit one (i.e. either the parent has no console, or the process was created with the CREATE_NEW_CONSOLE or CREATE_NO_WINDOW creation flag) or it will execute without a console if it's a detached process (i.e. the process was created with the DETACHED_PROCESS creation flag). You can pass these creation flags via the `creationflags` parameter of subprocess.Popen(). CREATE_NO_WINDOW is ignored if paired with either CREATE_NEW_CONSOLE or DETACHED_PROCESS, and the latter two obviously cannot be paired with each other. If you want to reuse the current console session, you'll have to spawn ssh, wait for it to exit, and proxy its exit status. That's the closest you can get to using exec*() in a POSIX system. --- [1] There's an unrelated concept of the active "Console" session in Windows terminal services. A Windows session contains a "WinSta0" interactive window station, which has input devices and a display and contains desktops such as the "Default" desktop, which contain windows. The "Console" session is the one that's connected to the physical console, i.e. the physical display, keyboard, and mouse. A Windows session also has the concept of a graphical shell, which is typically Windows Explorer. Generally speaking, however, the term "console" in Windows refers to a sub-session (i.e. subsystem) for text-based applications, which can exist in any Windows session, even in the non-interactive "Services" session. From ernst at pleiszenburg.de Thu May 13 06:34:13 2021 From: ernst at pleiszenburg.de (Sebastian M. Ernst) Date: Thu, 13 May 2021 12:34:13 +0200 Subject: [python-win32] Inheriting a command line - or how to efficiently replace Unix' os.execvpe In-Reply-To: References: Message-ID: <2a323588-850e-86a5-3a7d-db60e462656e@pleiszenburg.de> Hi Eryk, thanks a lot for the explanation. It's amazing how Windows does things differently in so many places ... > The grandparent and its grandchild will then compete with each other > for console I/O, which is an interleaved mess. You'll get a prompt > from the grandparent, but the text you enter will be read by the > grandchild. Then you'll get the grandchild's prompt, and so on. Yes, this is exactly what I have been observing so far. > If you want to reuse the current console session, you'll have to spawn > ssh, wait for it to exit, and proxy its exit status. That's the > closest you can get to using exec*() in a POSIX system. Yes, ideally I'd want to reuse the current console session, but I am failing at disentangling the "interleaved mess". > A console session doesn't implement the POSIX concept of foreground > and background process groups. Any process that's attached to a > console can read and write from it. Generally when one starts a child > process in the same console session, one either avoids using console > I/O until the child exits, or one simply blocks and does nothing while > waiting for the child to exit. Typically a command-line shell (e.g. > cmd.exe) implements the latter. If my Python process was "simply idling" / blocking, `ssh` could do its thing (fully interactively) in the meantime. Do I understand you correctly that this can actually be done? I have done a few dumb experiments along the lines of ... ```python proc = subprocess.Popen(['ssh', 'user at host'], **parameters) while proc.poll is None: time.sleep(0.25) ``` ... but I am not managing to specify `parameters` so that I can actually interact with `ssh`. Am I on the wrong track ... ? Best regards, Sebastian From eryksun at gmail.com Fri May 14 03:31:39 2021 From: eryksun at gmail.com (Eryk Sun) Date: Fri, 14 May 2021 02:31:39 -0500 Subject: [python-win32] Inheriting a command line - or how to efficiently replace Unix' os.execvpe In-Reply-To: <2a323588-850e-86a5-3a7d-db60e462656e@pleiszenburg.de> References: <2a323588-850e-86a5-3a7d-db60e462656e@pleiszenburg.de> Message-ID: On 5/13/21, Sebastian M. Ernst wrote: > > ... but I am not managing to specify `parameters` so that I can actually > interact with `ssh`. Am I on the wrong track ... ? It's not clear to me what you need. Do you need to spawn and wait for an interactive ssh session that's driven normally by the user? Or do you need expect-like automation of an ssh session? From mhammond at skippinet.com.au Sun May 30 20:54:33 2021 From: mhammond at skippinet.com.au (Mark Hammond) Date: Mon, 31 May 2021 10:54:33 +1000 Subject: [python-win32] [ANN] pywin32 build 301 released Message-ID: Hi all, I'm happy to announce the release of pywin32 build 301. There are a number of relatively small changes in this release. Downloads are available at: https://github.com/mhammond/pywin32/releases/tag/b301 and via pypi. For initial support (eg, to ask questions about the release etc), please contact this mailing-list (python-win32 at python.org). If you want to report a bug, please do so at https://github.com/mhammond/pywin32/issues As always, thanks to everyone who contributed to this release, both in terms of code and reporting bugs - there were a number of new contributors which is great to see, Cheers, Mark. Changes: Since build 300: ---------------- * Fix some confusion on how dynamic COM object properties work. The old code was confused, so there's a chance there will be some subtle regression here - please open a bug if you find anything, but this should fix #1427. * COM objects are now registered with the full path to pythoncomXX.dll, fixes #1704. * Creating a `win32crypt.CRYPT_ATTRIBUTE` object now correctly sets `cbData`. * Add wrap and unwrap operations defined in the GSSAPI to the sspi module and enhance the examples given in this module. (#1692, Emmanuel Coirier) * Fix a bug in `win32profile.GetEnvironmentStrings()` relating to environment variables with an equals sign (@maxim-krikun in #1661) * Fixed a bug where certain COM dates would fail to be converted to a Python datetime object with `ValueError: microsecond must be in 0..999999`. Shoutout to @hujiaxing for reporting and helping reproduce the issue (#1655) * Added win32com.shell.SHGetKnownFolderPath() and related constants. * CoClass objects should work better with special methods like __len__ etc. (#1699) * Shifted work in win32.lib.pywin32_bootstrap to Python's import system from manual path manipulations (@wkschwartz in #1651) * Fixed a bug where win32print.DeviceCapabilities would return strings containing the null character followed by junk characters. (#1654, #1660, Lincoln Puzey)