Page 1 of 1

[RESOLVED] Display of a selection window during installation

Published: January 20, 2025 - 4:08 PM
by Mikael S
Hello,

For a very specific task, I need to display a dialog box to select an action to perform during package installation on the machine receiving the installation.

I've been using `waptguihelper.grid_dialog` so far. However, this works fine with PyScripter, but only because it's my session. Installing packages from the console doesn't work.

I know the trick for executables using `get_active_sessions` and then `start_interactive_process`. But `grid_dialog` doesn't have a session parameter.

Is there a way to generate this dialog box for the active session and retrieve the selected action?




Sincerely,

Re: Displaying a selection window during installation

Published: January 20, 2025 - 4:39 PM
by sfonteneau
Good morning

We can ask the session to execute:

Code: Select all

waptpython -c "import json;import waptguihelper;waptguihelper.grid_dialog('hello',json.dumps({'hello':'hello'}))"
The problem is, I don't think the current code can retrieve the output value. We'd need to look into this further; it would be an interesting option

Re: Displaying a selection window during installation

Published: January 24, 2025 - 1:10 PM
by Mikael S
Indeed, there's no going back.

I tried using `print` to retrieve the output, but it doesn't seem as straightforward with the `win32process.CreateProcess` function at first glance.

I'll probably write it to a file and read it from the main program. For now, I don't see an easier way.

Re: Displaying a selection window during installation

Published: January 24, 2025 - 2:06 PM
by sfonteneau
I checked, I have something that works ;)

Code: Select all

# -*- coding: utf-8 -*-
from setuphelpers import *

import os
import win32api
import win32con
import win32process
import win32security
import win32ts
import win32profile
import win32pipe
import win32file

try:
    from waptenterprise.waptservice.enterprise import get_active_sessions
except:
    from waptservice.enterprise import get_active_sessions


def start_interactive_process2(app_filename, cmdline=None, session_id=None, hide=True, minimize=False):

    if session_id is None:
        session_id = win32ts.WTSGetActiveConsoleSessionId()
    if session_id == 0xffffffff:
        return None

    CREATE_BREAKAWAY_FROM_JOB = 0x1000000
    priority = win32con.NORMAL_PRIORITY_CLASS | win32con.CREATE_NO_WINDOW | CREATE_BREAKAWAY_FROM_JOB
    startup = win32process.STARTUPINFO()
    startup.lpDesktop = None
    startup.dwFlags = win32con.STARTF_USESTDHANDLES | win32con.STARTF_USESHOWWINDOW
    startup.wShowWindow = win32con.SW_HIDE

    token = win32ts.WTSQueryUserToken(session_id)


    saAttr = win32security.SECURITY_ATTRIBUTES()
    saAttr.bInheritHandle = True

    read_pipe, write_pipe = win32pipe.CreatePipe(saAttr, 0)
    win32api.SetHandleInformation(read_pipe, win32con.HANDLE_FLAG_INHERIT, 0)


    startup.hStdOutput = write_pipe
    startup.hStdError = write_pipe
    startup.hStdInput = win32api.GetStdHandle(win32api.STD_INPUT_HANDLE)

    if cmdline is None:
        cmd = f'"{app_filename}"'
    else:
        cmd = f'"{app_filename}" {cmdline}'

    working_directory = "C:\\Windows\\System32"

    environment = win32profile.CreateEnvironmentBlock(token, False)
    new_token = win32security.DuplicateTokenEx(token, win32security.SecurityDelegation, win32security.TOKEN_ALL_ACCESS, win32security.TokenPrimary)

    process_info = win32process.CreateProcessAsUser(
        new_token,
        None,
        f'cmd.exe /c {cmd}',
        None, None,
        True,
        priority,
        environment,
        working_directory,
        startup
    )

    win32api.CloseHandle(token)
    win32api.CloseHandle(new_token)

    win32file.CloseHandle(write_pipe)

    output = b""
    while True:
        try:
            chunk = win32file.ReadFile(read_pipe, 4096)[1]
            if not chunk:
                break
            output += chunk
        except Exception:
            break

    win32file.CloseHandle(read_pipe)

    return output.decode("utf-8", errors="ignore")




def install():
    list_session = get_active_sessions()
    for s in list_session:
        output = start_interactive_process2('''waptpythonw -c "import json;import waptguihelper;print(waptguihelper.grid_dialog('hello',json.dumps({'hello':'hello'})))"''',session_id=s)
        print(output)
However, it's up to you to manage the while loop to avoid an infinite wait

Re: Displaying a selection window during installation

Published: February 4, 2025 - 10:22 AM
by Mikael S
Okay, that works. It was a bit complex to pass all the arguments with quotes and retrieve the values, especially since it's a list of values ​​that I'm sending.

But for those who are interested, here's part of the code

Code: Select all

titre = "'Choix'"
json_list_backup = json.dumps(list_choix).replace('"', "'")

command_line = f'import json;import waptguihelper;print(waptguihelper.grid_dialog({titre},{json_list}, waptguihelper.GRT_SELECTED))'
list_session = get_active_sessions()
for s in list_session:
    selected_backup = ast.literal_eval(start_interactive_process2(f'waptpythonw -c "{command_line}"', session_id=s))
However, the loop seems fine to me. I don't see in what scenario it could cause a problem.

Re: Displaying a selection window during installation

Published: February 4, 2025 - 11:59 AM
by dcardon
Hi Mikaël,

thanks for the feedback :-), I'm marking the topic as RESOLVED.

Denis