来自 Python 可执行文件的 NTEventLogHandler

2024-03-12

import logging, logging.handlers

def main():
    ntl = logging.handlers.NTEventLogHandler("Python Logging Test")
    logger = logging.getLogger("")
    logger.setLevel(logging.DEBUG)
    logger.addHandler(ntl)
    logger.error("This is a '%s' message", "Error")


if __name__ == "__main__":
    main()

上面的 Python (2.7.x) 脚本将“这是一条‘错误’消息”写入 Windows 事件查看器。当我将其作为脚本运行时,我得到了预期的输出。如果我通过 PyInstaller 将脚本转换为可执行文件,我会在事件日志中获得一个条目,但它会显示完全不同的内容。

无法在源(Python 日志记录测试)中找到事件 ID (1) 的描述。本地计算机可能没有必要的注册表信息或消息 DLL 文件来显示来自远程计算机的消息。您可以使用 /AUXSOURCE= 标志来检索此描述;有关详细信息,请参阅帮助和支持。以下信息是该事件的一部分: 这是一条“错误”消息。

这是我用来将脚本转换为可执行文件的命令:pyinstaller.py --onefile --noconsole my_script.py尽管命令行参数似乎对此行为没有任何影响,只需调用就足够了pyinstaller.py my_script.py.

如果您能帮助我了解发生的情况以及我如何解决此问题,我将不胜感激。

最终解决方案

我不想走资源黑客的路线,因为这将是自动化的一个困难步骤。相反,我采取的方法是抓住win32service.pyd文件来自 c:\Python27\Lib\site-packages\win32 并将其放在我的可执行文件旁边。然后修改脚本,将完整路径传递给win32service.pyd文件,并且可以以脚本和 exe 形式运行。最终脚本如下:

import logging, logging.handlers
import os
import sys

def main():
    base_dir = os.path.dirname(sys.argv[0])
    dllname = os.path.join(base_dir, "win32service.pyd")

    ntl = logging.handlers.NTEventLogHandler("Python Logging Test", dllname=dllname)
    logger = logging.getLogger("")
    logger.setLevel(logging.DEBUG)
    logger.addHandler(ntl)
    logger.error("This is a '%s' message", "Error")


if __name__ == "__main__":
    main()

通常,Windows 事件日志不会以纯文本形式存储错误消息,而是存储消息 ID 引用和插入字符串。

而不是存储像这样的消息Service foo crashed unexpectedly,它存储一个消息 ID,该 ID 指向存储在 DLL 中的资源字符串。在这种情况下,资源将类似于Service %s crashed unexpectedly and foo将存储为插入字符串。写入消息的程序注册资源DLL。

其原因在于本地化。 DLL 可以存储大量不同的资源(对话框布局、字符串、图标……),并且一个 DLL 可以包含多种不同语言的相同资源。操作系统根据系统区域设置自动选择正确的资源。几乎所有 Microsoft 实用程序和核心实用程序都使用资源 DLL。

Side note: Nowadays, the preferred (and cross-platform) way for localization is gettext.

这也用于消息日志 - 理想情况下,您可以在英语 Windows 上打开德语 Windows 安装的日志,其中所有消息均为英语。

我怀疑 pywin32 实现通过只有一个消息 ID (1) 来跳过该机制,就像这样"%s"。它存储在win32service.pyd并由 pywin32 注册。只要该文件存在于文件系统上,它就可以正常工作,但一旦它隐藏在 PyInstaller 可执行文件中,就会中断。我猜你必须将消息 ID 直接嵌入到可执行文件中。

Edit:怀疑得到证实,消息表确实存放在里面win32service.pyd

资源黑客显示消息表 http://media.leoluk.de/evlog_rh.png http://media.leoluk.de/evlog_rh.png

尝试从复制消息表资源win32service.pyd到您的 PyInstaller 可执行文件(例如使用资源黑客 http://media.leoluk.de/evlog_rh.png).

查看日志处理程序的实现,这可能有效:

def __init__(self, appname, dllname=None, logtype="Application"):
    logging.Handler.__init__(self)
    try:
        import win32evtlogutil, win32evtlog
        self.appname = appname
        self._welu = win32evtlogutil
        if not dllname:
            dllname = os.path.split(self._welu.__file__)
            dllname = os.path.split(dllname[0])
            dllname = os.path.join(dllname[0], r'win32service.pyd')

你必须设置dllname to os.path.dirname(__file__)。如果您希望它继续为未冻结的脚本工作,请使用类似的内容:

if getattr(sys, 'frozen', False):
    dllname = None
elif __file__:
    dllname = os.path.dirname(__file__)

ntl = logging.handlers.NTEventLogHandler("Python Logging Test", dllname=dllname)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

来自 Python 可执行文件的 NTEventLogHandler 的相关文章

随机推荐

  • Git 分支命名规则[重复]

    这个问题在这里已经有答案了 当我在 Git 中命名分支时 我总是倾向于以字母开头 mybranch89例如 Git 分支的命名有什么规则吗 例如 我应该始终以字母开头 还是只能使用数字分支名称 例如876 规则是相当复杂 http git
  • 在 TextView 中显示图像

    我希望在 TextView 中显示图像 我的图像保存在 res raw 目录中 我尝试使用 HTML ImageGetter 但找不到相同的完整参考 import android app Activity import android gr
  • 追踪事务为何升级为 DTC

    有什么方法可以准确确定 System Transaction TrasactionScope 升级为 DTC 的原因吗 我们的一个组件遇到了麻烦 该组件似乎升级了交易 而所有其他组件 看起来看似相似 却没有升级 是否提供了有关升级原因以及如
  • 如何在Python中查找字符串中的一个数字?

    我有一个名为 FILE 1 txt 或 FILE 340 txt 的文件 我希望能够从文件名中获取数字 我发现我可以使用 numbers re findall r d s filename 获取包含数字的列表 并使用numbers 0 将数
  • 什么时候应该使用 XS?

    我正在写一篇关于 XS 的演讲 我需要知道社区何时认为适合采用 XS 我可以想到至少三个使用 XS 的理由 您有一个想要在 Perl 5 中访问的 C 库 您有一段代码 它确实会减慢您的程序速度 如果用 C 编写 速度会更快 您需要访问仅在
  • 想在Mysql中为两个不同的数据库编写触发器

    有没有办法在Mysql中的两个不同的数据库上创建触发器 我的要求是这样的 database test1 gt table tmp1 database test2 gt table tmp2 现在我必须在 test1 上使用触发器插入操作发生
  • 错误:没有匹配的函数来调用“Point::Point()”

    因此 我创建了 Point 类 并希望将其用作 Circle 类中构造函数的参数 但出现错误 没有显示类 Point 的默认构造函数 我不知道如何修复它 代码如下所示 class Point private int x y public P
  • 使用android的sip进行Android音频通话

    我为客户开发了一个使用 sip 进行互联网呼叫的应用程序 为此 他向我提供了两个有效的 sip 用户 ID 和密码 我正在使用 SIP API 进行 SIP 实施 客户说呼叫无法进行 当他使用自己的帐户登录时 他没有收到任何有关未接来电的通
  • 动态渲染vue模板

    我有 vue 模板数据作为字符串 例如 String s div myData div 现在我想在我已经定义的 vue 组件中进行渲染
  • Laravel 如何测试控制器中的复选框是否被选中

    我试图获取复选框是否已选中 在我看来
  • ASP.NET MVC 项目中的 Web 表单?

    我需要向 ASP NET MVC 项目添加一个 管理 区域 并且我需要它来使用 ASP NET Web 窗体 而不是 MVC ASP NET Web 窗体可以在 ASP NET MVC 应用程序中使用吗 我在 MVC 项目中有类似的东西 因
  • vtable存放在内存的什么位置?

    vtable存放在内存的什么位置 取决于编译器 在 VC 中 vtable 指针存储在对象分配的开始处 位于任何成员数据之前 前提是您的类至少有一个虚拟成员函数 如果您的类从具有虚函数表的其他类进行多重继承 则还可能有多个虚函数表指针 vt
  • 如何使用 JavaScript 从 Web 服务返回的二进制字符串构建 PDF 文件

    我正在尝试从二进制流中构建一个 PDF 文件 该文件是我收到的 Ajax 请求的响应 Via XmlHttpRequest我收到以下数据 PDF 1 4 hole data representing the file EOF 到目前为止我尝
  • jqgrid - 调整大小和覆盖

    HTML
  • Canvas 对象未显示,但位置在 Java Applet 中正确更新

    我的基本弹跳球小程序应该有一个球根据中的值移动loc变量 但什么也没有显示 打印输出loc表明移动它和弹离边界背后的数字 数学确实按其应有的方式工作 但没有任何显示 查看在线示例 我不明白为什么我的绘图 绘画代码没有按预期工作 这就是我所拥
  • 为轮播创建循环时出现问题 - 回到第一个元素

    我在轮播中创建循环时遇到问题 因此在单击事件 rightButton 上到达最后一张卡后它将返回到第一张卡 到目前为止 轮播在到达最后一张卡时停止 const carousel document querySelector data tar
  • Android 单元测试:在测试活动之前清除首选项

    我想确保在我之前清除首选项Activity在我的单元测试中开始 问题是要清除首选项 您需要调用getActivity 之后 Activity启动 它会读取首选项 Override protected void setUp throws Ex
  • 在 Immutable.js 中从 Map 内的 List 中删除元素的最佳方法

    我在用Facebook 的 Immutable js http facebook github io immutable js 加速我的 React 应用程序以利用PureRender混合 https facebook github io
  • 如何在 Firemonkey 中创建“禁止激活”表单

    在 XCode 中 通过将这些方法添加到 NSView 子类中可以防止窗口在单击时变为活动状态 BOOL shouldDelayWindowOrderingForEvent NSEvent theEvent return YES BOOL
  • 来自 Python 可执行文件的 NTEventLogHandler

    import logging logging handlers def main ntl logging handlers NTEventLogHandler Python Logging Test logger logging getLo