【问题标题】:How to close the xxxxx.exe terminal window without killing the xxxxx process?如何在不杀死 xxxxx 进程的情况下关闭 xxxxx.exe 终端窗口?
【发布时间】:2013-08-22 05:04:37
【问题描述】:

这个 Emacs 命令 (make-comint-in-buffer "Python" nil "python" nil "-i")(make-comint-in-buffer "git" nil "C:/Program Files (x86)/Git/bin/sh.exe" nil "--login" "-i") 如何在 Emacs 缓冲区中获取提示并在不终止 Python 进程的情况下使用它的 Python/sh.exe 交互式终端?

我试图通过深入了解make-comint-in-buffer 的源代码来弄清楚,但遇到了processp,这是C 编译的代码,我无法找到它的源代码find

我问这个问题的原因是在不使用pythonw 的情况下找到this 问题的替代答案(例如,它们不是mayapyw.exemayapy.exe)。

【问题讨论】:

  • 您必须提前决定将程序作为控制台应用程序还是窗口应用程序运行,这是 Windows 的一个基本限制。这就是为什么“pythonw”和“.pyw”这些东西首先存在的原因——它们在其他操作系统中不存在,因为它们不必存在;一个程序可以在它开始运行后决定那种事情。因此,如果您在控制台应用程序中,则必须将子应用程序作为窗口应用程序运行,或者生成一个新的 shell 进程(和新窗口)。

标签: emacs terminal stdout createprocess


【解决方案1】:

Emacs 使用 SHOWWINDOW 标志来 CreateProcess 来控制与子进程关联的控制台窗口的显示。

create_child in w32proc.c的关键码是:

if (NILP (Vw32_start_process_show_window) && !is_gui_app)
    start.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
else
    start.dwFlags = STARTF_USESTDHANDLES;

start.wShowWindow = SW_HIDE;

if (!CreateProcess (exe, cmdline, &sec_attrs, NULL, TRUE, flags, env, dir, &start, &cp->procinfo))
{ ...
}

【讨论】:

    【解决方案2】:

    我只能猜测 Emacs 命令是如何工作的,因此无法真正帮助您……但是,我可以为您提供一种隐藏窗口的方法。这可以通过使用 CTypes 模块并调用 Windows-API 来获取 Window/Python-prompts ID/Hwin,然后隐藏该窗口。

    这会迫使您在脚本中导入/或包含这段代码,然后在脚本中调用一个函数/做一些事情。一旦你的脚本运行,这应该隐藏提示。用法见"main.py"-part。

    Window.py

    from ctypes import *
    
    user32 = windll.user32
    
    BOOL    = c_bool
    INT     = c_int
    LONG    = c_long
    LPVOID  = c_void_p
    LPTSTR  = c_wchar_p
    HWND    = LPVOID
    LPARAM  = LPVOID
    
    GW_OWNER = 4
    GWL_EXSTYLE  = -20
    WS_EX_TOOLWINDOW = 128
    WS_EX_APPWINDOW = 262144
    
    #------------------------------------------------------------------------ 
    
    def GetWindowLong(hwnd, index):
        user32.GetWindowLongW.argtypes = [HWND, INT]
        return user32.GetWindowLongW(hwnd, index)
    
    def GetWindow(hWnd, uCmd):
        user32.GetParent.argtypes = [HWND, INT]
        return user32.GetWindow(hWnd, uCmd)
    
    def GetParent(hwnd):
        user32.GetParent.argtypes = [HWND]
        return user32.GetParent(hwnd)
    
    def IsWindowVisible(hwnd): 
        user32.IsWindowVisible.argtypes = [HWND]
        return user32.IsWindowVisible(hwnd)
    
    def GetWindowTextLength(hwnd):
        user32.GetWindowTextLengthW.argtypes = [HWND]
        return user32.GetWindowTextLengthW(hwnd)
    
    def GetWindowText(hwnd):
        length = GetWindowTextLength(hwnd)
        if not length: return False
        buff = create_unicode_buffer(length + 1)
        user32.GetWindowTextW.argtypes = [HWND, LPTSTR, INT]
        res = user32.GetWindowTextW(hwnd, buff, length + 1)   
        if res: return buff.value
        else: return False  
    
    def isRealWindow(hwnd):
        """ Check if a given window is a real Windows application frame..
            Returns a BOOL """
    
        if not IsWindowVisible(hwnd):
            return False
        if GetParent(hwnd) != 0:
            return False
        hasNoOwner = GetWindow(hwnd, GW_OWNER) == 0
        lExStyle = GetWindowLong(hwnd, GWL_EXSTYLE)
        if (((lExStyle & WS_EX_TOOLWINDOW) == 0 and hasNoOwner)
          or ((lExStyle & WS_EX_APPWINDOW != 0) and not hasNoOwner)):
            if GetWindowText(hwnd):
                return True
        return False
    
    class WindowEnumerator(object):
        """ Window enumerator class.  You can pass it's instances
            as callback functions in window enumeration APIs. """
    
        def __init__(self):
            self.hwnd = []
    
        def __call__(self, hwnd, lParam):
            self.hwnd.append(hwnd)
            return True
    
    class __EnumWndProc(WindowEnumerator):
        pass
    
    def EnumWindows():
        WNDENUMPROC = WINFUNCTYPE(BOOL,HWND,LPARAM)
        _EnumWindows = user32.EnumWindows
        _EnumWindows.argtypes = [WNDENUMPROC, LPARAM]
        _EnumWindows.restype  = BOOL
    
        EnumFunc = __EnumWndProc()
        lpEnumFunc = WNDENUMPROC(EnumFunc)
        if not _EnumWindows(lpEnumFunc, None):
            errcode = GetLastError()
            if errcode not in (ERROR_NO_MORE_FILES, ERROR_SUCCESS):
                raise WinError(errcode)
        return EnumFunc.hwnd
    
    def GetWindowByName(title):
        window = []
        hwnds = EnumWindows()
        for hwnd in hwnds:
            if not isRealWindow(hwnd):
                pass
            else:
                wndtitle = GetWindowText(hwnd)
                if title.lower() in wndtitle.lower():
                    return (hwnd, wndtitle)
        return False
    
    def ShowWindow(hWnd, arg=0):
        user32.ShowWindow.argtypes = [HWND, c_int]
        return user32.ShowWindow(hWnd, arg)
    

    ma​​in.py

    import Window
    
    # Pass the full or partial title of the window that should be hidden.
    wnd = Window.GetWindowByName('xxxxxxx.exe')
    if wnd:
        Window.ShowWindow(wnd[0], 0) #Hide it. 0=SW_HIDE, 5 = SW_SHOW.
    

    我希望这能解决问题。

    【讨论】:

      猜你喜欢
      • 2021-07-24
      • 2022-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-09
      • 1970-01-01
      相关资源
      最近更新 更多