python-3.x - 如何获取 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
::
class CDLL(object)
:
此类的一个实例代表一个加载的 dll/共享库,使用标准 C 调用约定(在 Windows 上名为“cdecl”)导出函数。
导出的函数可以作为属性访问,也可以通过函数名索引来访问。例子:
<obj>.qsort
-> 可调用对象
<obj>['qsort']
-> 可调用对象调用函数会在调用期间释放 Python GIL,然后再重新获取它。
class PyDLL(CDLL)
:
此类代表 Python 库本身。它允许访问 Python API 函数。GIL 未发布,Python 异常处理正确。
然后if _os.name == "nt"
:
class WinDLL(CDLL)
:
此类表示使用 Windows stdcall 调用约定的 dll 导出函数。
从讨论评论:
stdcall
:
stdcall[4] 调用约定是 Pascal 调用约定的变体,其中被调用者负责清理堆栈,但参数按从右到左的顺序压入堆栈,就像在
_cdecl
调用约定中一样。寄存器 EAX、ECX 和 EDX 被指定在函数中使用。返回值存储在 EAX 寄存器中。
stdcall
是 Microsoft Win32 API 和 Open Watcom C++ 的标准调用约定。
解决方案
推荐阅读
- java - 转换模型的最佳方法
- docker - 如何用 Docker 覆盖超集 javascript 文件?
- php - Laravel Eloquent 如何从数组中获取结果
- beautifulsoup - 缺少使用 beautifulsoup 提取文本
- c# - 使用访问令牌安全地进行身份验证
- node.js - 如何从 Visual Studio 调试 C++ Electron 插件
- typescript - 使用 react-native-typescript-transformer 编译 TypeScript?
- c++ - 如何在 IBM ILOG CPLEX 优化工作室中使用 c++ 或 java 库
- javascript - 父组件外的 Vue 内容渲染
- javascript - 在 For 循环中添加事件侦听器