微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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

当在没有WM_CLOSE选项的进程上使用taskkill时,是否可以处理Windows发送的/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 window

taskkill在不带/F标志的情况下使用时,会向与您在调用{{1}时使用的pid关联的窗口句柄发送WM_CLOSEWM_QUIT消息}

Difference between taskkill and taskkill /f

请注意,我使用的是Windows 10,因此必须赶上taskkill而不是WM_CLOSE

您可以通过打开命令提示符并运行ffmpeg,然后尝试进行WM_QUITtaskkill /PID {pid}来自己测试问题。 ffmpeg将继续编码/记录,taskkill /IM ffmpeg.exe会告诉您它已成功杀死该进程。

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 关闭ffmpeg进程的演示。 taskkill的默认行为是未处理的,因为ffmpeg不会创建可以向其发送taskkill事件的窗口句柄。

https://imgur.com/a/JxGjiiX

^我使用自定义的ffmpeg包装器捕获了WM_CLOSE事件,并正常关闭了ffmpeg来记录此剪辑。

解决方案

将窗口与Windows上的任何可执行文件相关联的一种方法是使用启动命令:

WM_CLOSE

然后,您可以使用start "Your window title" program.exe -option1 -option2发送taskkill事件,该事件可以被拦截,但是ffmpeg实际上并没有捕获到该事件,因为它最初并不是为捕获该事件而设计的。

要在WM_CLOSE中解决此问题,您可以结合使用3个其他模块来创建窗口句柄,启动/监视进程并拦截nim事件并将“ q”写入ffmpeg进程的WM_CLOSE

wNim

winim

nimpy

在其他版本的Windows中,stdout发送taskkill事件,因此您可能也需要处理该事件。

使用WM_QUIT创建窗口句柄; wNim仅用于访问用于winim事件处理程序的WM_CLOSE常量。

wNim

使用nimpy加载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. 文件,以便您可以使用python中的python3.8.dll模块。 (比内置的subprocess多处理库imho更易于使用)

nim

创建事件处理程序。这些将处理应用程序的首次启动以及Windows中的# 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

然后需要做的就是将框架居中并启动应用程序。

# 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)

请记住,这使用的是python标准库,因此您需要将python dll放入以下文件夹中,以便frame.center() app.mainLoop() 进行访问。

nimpy

这是一个存储库,其中包含您碰巧遇到同一问题所需的一切:

https://github.com/Wykleph/ffmpeg_wrapper

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。