首页 > 解决方案 > 如何获取 Windows STDOUT 句柄(在 python 中)的句柄?

问题描述

我正在尝试处理 Windows标准输出句柄。

我需要了解为什么 STDOUT 有不同的句柄(CONOUT$?)以及如何解释这些差异。我知道 Windows API 使用了不同的输出缓冲区,但无法理解(来自许多 MSDN 文档)何时以及如何使用它们。

使用ctypes和 python3,我可以通过下面的脚本获得其中的 2 个。mintty/bash但是,在 (Cygwin) 、PowerShell(6.1.1)CMD甚至中运行脚本ConEmu都会产生略有不同的结果。

在 mintty 中,所有标准输出句柄都是相同的,而在 PowerShell 中它们是不同的。到底是怎么回事?

问题:
为什么 stdout 句柄是由:获得的,_get_osfhandle并且GetStdHandle不同?

这是我的代码:

#!/usr/bin/env python3
#-*- coding: utf-8 -*-
#----------------------------------------------------------------------------
import sys
import ctypes
from ctypes import cdll, c_ulong

def color(text, color_code):
    return '\x1b[%sm%s\x1b[0m' % (color_code, text)
def byellow(text): return color(text, '1;49;33')
def printHex(mode):
    return byellow("0x%04x  (%s)" % (mode, mode))   # DWORD

kFile = 'C:\\Windows\\System32\\kernel32.dll'
mFile = 'C:\\Windows\\System32\\msvcrt.dll'

print("\n Getting Console STDOUT handles using 2 different methods:")

try: 
    k32    = cdll.LoadLibrary(kFile)
    msvcrt = cdll.LoadLibrary(mFile)
except OSError as e:
    print("ERROR: %s" % e)
    sys.exit(1)

try: 
    hmsvcrt_osf = msvcrt._get_osfhandle(sys.stdout.fileno())    # Get the parent (?) process Console Output buffer Handle
    hk32_11     = k32.GetStdHandle(-11)                         # Get the current process Console Output buffer Handle
except Exception as e:
    print("ERROR: %s" % e)
    sys.exit(1)

print(" Got stdout handles using:\n")
print("   msvcrt._get_osfhandle : %s" % printHex(hmsvcrt_osf))
print("   k32.GetStdHandle(-11) : %s" % printHex(hk32_11))

这是输出:

# In PowerShell
# python3.6m.exe .\testHandles.py

 Getting STDOUT handles using 2 different methods:
 Got stdout handles using:

   msvcrt._get_osfhandle : 0x001c  (28)
   k32.GetStdHandle(-11) : 0x014c  (332)

# In Cygwin
# ./testHandles.py

 Getting STDOUT handles using 2 different methods:
 Got stdout handles using:

   msvcrt._get_osfhandle : 0x0338  (824)
   k32.GetStdHandle(-11) : 0x0338  (824)

# pwsh.exe -NoProfile -c "python3.6m.exe C:\test\testHandles.py"

 Getting STDOUT handles using 2 different methods:
 Got stdout handles using:

   msvcrt._get_osfhandle : 0x0338  (824)
   k32.GetStdHandle(-11) : 0x0144  (324)

根据 MSDN:

相关问题:


附录:2018-12-14

/usr/lib/python3.6/ctypes/__init__.py::

此类的一个实例代表一个加载的 dll/共享库,使用标准 C 调用约定(在 Windows 上名为“cdecl”)导出函数。

导出的函数可以作为属性访问,也可以通过函数名索引来访问。例子:

<obj>.qsort-> 可调用对象

<obj>['qsort']-> 可调用对象

调用函数会在调用期间释放 Python GIL,然后再重新获取它。

此类代表 Python 库本身。它允许访问 Python API 函数。GIL 未发布,Python 异常处理正确。

然后if _os.name == "nt"

此类表示使用 Windows stdcall 调用约定的 dll 导出函数。


从讨论评论:

stdcall

stdcall[4] 调用约定是 Pascal 调用约定的变体,其中被调用者负责清理堆栈,但参数按从右到左的顺序压入堆栈,就像在_cdecl调用约定中一样。寄存器 EAX、ECX 和 EDX 被指定在函数中使用。返回值存储在 EAX 寄存器中。

stdcall是 Microsoft Win32 API 和 Open Watcom C++ 的标准调用约定。

标签: python-3.xwindowswinapistdoutmsvcrt

解决方案


推荐阅读