gpt4 book ai didi

windows - 如何使用 nim 语言在 Windows 上处理 taskkilll 命令?

转载 作者:行者123 更新时间:2023-12-03 11:10:10 24 4
gpt4 key购买 nike

有没有办法处理 WM_CLOSE Windows 在 taskkill 时发送的事件用于没有 /F 的进程选项? ffmpeg 不是为了捕捉这个事件而设计的,我想写一个 nim可以管理 ffmpeg 进程并告诉它在收到 WM_CLOSE 时正常关闭的程序事件。我对 Windows API 和 nim 非常陌生,所以我不知道从哪里开始。
这是一个显示 ffmpeg https://imgur.com/a/JxGjiiX 问题的 gif。
如果我用 /F 强行终止 ffmpeg 进程选项它将在编码/录制期间以文件损坏结束。
这是我用来测试此功能的代码:

import os, times, strutils


let t = epochTime()

proc handler() {.noconv.} =
echo "Program has run for ", formatFloat(epochTime() - t, precision = 0), " seconds."
quit(0)

setControlCHook(handler)

while true:
sleep 500

这不会捕获 WM_CLOSE taskkill 生成的事件.
我怎样才能使我的 nim程序捕获 WM_CLOSE事件?

最佳答案

问题
如果没有与进程关联的窗口句柄,则无法捕获 WM_CLOSE事件 taskkill在没有 /F 的情况下使用时发送旗帜。
Send WM_CLOSE message to a process with no windowtaskkill , 不使用 /F 时标志,发送 WM_CLOSEWM_QUIT与您在调用 taskkill 时使用的 pid 关联的窗口句柄的消息
Difference between taskkill and taskkill /f
请注意,我在 Windows 10 上,所以我必须 catch WM_CLOSE而不是 WM_QUIT您可以通过打开命令提示符并运行 ffmpeg 自己测试问题,然后尝试 taskkill /PID {pid}taskkill /IM ffmpeg.exe . ffmpeg 将继续编码/记录和taskkill会告诉你它成功杀死了进程。

ffmpeg.exe -rtbufsize 150M -f gdigrab -framerate 30 -offset_x 448 -offset_y 240 -video_size 1024x600 -draw_mouse 1 -show_region 1 -i desktop -r 30 -preset ultrafast -tune zerolatency -movflags +faststart output.mp4
这是尝试使用 taskkill 关闭 ffmpeg 进程的演示. taskkill 的默认行为未处理,因为 ffmpeg 没有创建可以具有 WM_CLOSE 的窗口句柄事件发送给它。
https://imgur.com/a/JxGjiiX
^ 我使用我的自定义 ffmpeg 包装器来捕获 WM_CLOSE事件并优雅地关闭 ffmpeg 以录制此剪辑。
解决方案
将窗口与 Windows 上的任何可执行文件关联的一种方法是使用 start 命令: start "Your window title" program.exe -option1 -option2然后您可以使用 taskkill发送 WM_CLOSE事件,它可以被拦截,但 ffmpeg 实际上并没有捕捉到这个事件,因为它最初并不是为了捕捉它而设计的。
nim 中解决此问题,您可以使用 3 个附加模块的组合来创建窗口句柄,启动/监视进程,并拦截 WM_CLOSE事件并将“q”写入ffmpeg进程的 stdout .
wNim
winim
nimpy
在其他版本的 windows taskkill发送 WM_QUIT事件,因此您可能还需要处理它。
使用 wNim 创建窗口句柄; winim仅用于访问 WM_CLOSE用于 wNim 的常量事件处理程序。
import os
import wnim
import winim
import nimpy

# Put python3.8.dll into following folder. It is required by nimpy
# C:/Users/username/AppData/Local/Microsoft/WindowsApps

let app = App()
let frame = Frame(title="ffmpeg", size=(400, 300)) # Size doesn't matter because we never show the frame.
加载 python3.8.dll文件使用 nimpy所以你可以使用 subprocess来自python的模块。 (比内置的 nim 多处理库 imho 更易于使用)
# This is used to check if ffmpeg has been launched
var running_process = false

# The process must be a PyObject, not a Process object from nim
var the_proc: PyObject

# Get reference to the subprocess module
let subprocess = pyImport("subprocess")

# Get reference to python builtin modules
let py = pyBuiltinsModule()

# Get a reference to the subprocess PIPE
let pipe = subprocess.PIPE
创建事件处理程序。这些将处理应用程序的首次启动和 WM_CLOSE Windows 中的事件。
# We catch the WM_MOVE event and start the process.
# We force the event to trigger when we center
# the frame and start the app.
frame.connect(WM_MOVE) do (event: wEvent):
# Make sure we only start 1 process.
if running_process == false:
running_process = true

# Create command and start the process.
var command_str: string = paramStr(1)
for i in 2..paramCount():
command_str = command_str & " " & paramStr(i)

# Use python subprocess module to execute command and set the stdin to the pipe.
the_proc = subprocess.Popen(command_str, stdin=pipe)

# When WM_CLOSE is triggered from taskkill, write the utf-8 encoded "q"
# to the ffmpeg process
frame.connect(WM_CLOSE) do (event: wEvent):
var command = "q"
# Make sure objects are all safe to use
# They should by python objects. Call the
# standard library to create the python objects.
var pycommand = py.str.encode(py.str(command), "utf-8")

# With a python process you call `communicate` on
# the process when you want it to wait to complete.
# Since ffmpeg just needs the "q" character we send
# the utf-8 encoded "q" with the `input` keyword
discard the_proc.communicate(input=pycommand)
sleep(1000)

# Get rid of process and quit.
discard the_proc.terminate()
quit(0)
然后所有需要做的就是使框架居中并启动应用程序。
frame.center()
app.mainLoop()

请记住,这使用了python标准库,因此您需要将python dll放入以下文件夹中 nimpy获得访问权。 C:/Users/username/AppData/Local/Microsoft/WindowsApps如果您碰巧遇到相同的问题,这里有一个存储库,其中包含您需要的一切:
https://github.com/Wykleph/ffmpeg_wrapper

关于windows - 如何使用 nim 语言在 Windows 上处理 taskkilll 命令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63649070/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com