在 Notepad++ 中以选项卡形式打开文件,无需关闭启动的进程

在 Notepad++ 中以选项卡形式打开文件,无需关闭启动的进程

一些旧工具设计用于与外部文本编辑器配合使用。我只能使用以下方式执行此操作的旧工具:

  1. 创建一个临时文件,其中包含要编辑的内容。
  2. 启动用户指定的应用程序,并将临时文件的路径作为参数添加。
  3. 等待启动的应用程序关闭(可能监视PID)
  4. 使用修改日期字段检查临时文件是否已更新,并加载更新的数据。

我一直试图将此工具(无法轻易更改)与 Notepad++ 一起使用。我遇到了一些问题,因为该工具仅监视临时文件,直到它启动的应用程序关闭。启动 Notepad++ 进程的新实例时,默认行为是将文件作为选项卡在任何已打开的 Notepad++ 实例中打开并关闭新进程。这导致该工具认为编辑器已立即关闭,然后错过实际发生的任何编辑。

我可以通过使用 -multiInst 命令行参数强制 Notepad++ 始终在新实例中启动来解决此问题。我希望能够以选项卡形式打开临时文件,因为我还使用了一些可跨选项卡(但不能跨实例)工作的 Notepad++ 插件。

有人有解决方案吗?如果我可以让 Notepad++ 将文件作为选项卡打开,但在文件仍打开时仍将启动的进程保留在内存中,那就太好了。我猜这类似于 Chrome 使用的每个选项卡一个进程的模型。我也考虑过通过批处理文件或类似文件间接启动 Notepad++,但我不知道如何检测 Notepad++ 中选项卡/文件何时关闭。

答案1

您必须向您的旧式应用程序提供单独进程的 PID,以跨越文件版本。

不幸的是,我所知道的所有检测文件版本结束的简单方法都不起作用 - Notepad ++:

  • 不要保持文件句柄处于打开状态。
  • 具有自定义绘制的选项卡控件。
  • 不要在注册表中保存最近的文件列表。

因此,如果不编写 npp 插件 - 它处理 NPPN_FILECLOSED 通知 - 我看不到除了通过以下方式启动 Notepad ++ 之外的解决方案run_npp_cmd

@echo off
start C:\your\path\to\notepad++.exe %1
echo Do your work and then let me go
pause

您可以run_npp_cmd C:\path\to\your\data.txt从旧应用程序中调用,并且当您完成工作时,您可以让命令行实例运行......

答案2

我认为我已经想出了一个概念验证解决方案,但它有点复杂,并且(目前)会导致 Notepad++ 崩溃,因此目前可能还不可行。我想无论如何都会发布它,因为其他人可能正在考虑解决类似的问题。

测试版插件Notepad++ Python 脚本添加对 Notepad++ 中脚本的支持,包括挂接到现有的 Notepad++ 通知。该插件包含一个启动脚本,只要在插件的配置选项中选择了“ATSTARTUP”,该脚本就会始终运行。

  1. 从旧工具启动批处理文件(可以在启动时最小化)
  2. 将命令窗口标题更改为 Notepad++ 已知的唯一名称(文件名可能可以),以便以后可以将其终止
  3. 使用批处理文件作为命令行参数启动 Notepad++
  4. 自动注册一个python函数作为启动时FILEBEFORECLOSE通知的回调
  5. 当文件关闭时,使用文件名重建命令提示符的窗口标题并使用它来终止它。

这成功导致命令窗口关闭,但随后 Notepad++ 锁定。我认为这是 Python 插件的问题。似乎从通知回调调用 console.run() 会导致问题。我知道该命令格式正确,因为它在从用户触发的脚本运行时不会崩溃。每次关闭文件时都会运行此脚本,它会导致 Notepad++ 挂起,因此我不建议您在当前状态下使用此解决方案

从旧版工具运行的命令:

start /min nppblock.bat

notepadpp_blocker.bat:

@echo off
FOR %%i IN (%1) DO (
    set filename=%~nx1
)
title=nppblock_%filename%
echo Waiting for %filename% to be closed in Notepad++
"C:\Program Files (x86)\Notepad++\notepad++.exe" %1
pause

添加到 C:\Program Files (x86)\Notepad++\plugins\PythonScript\scripts\startup.py:

import os.path
def fileBeforeCloseCallback(args):
    filename = os.path.basename(notepad.getBufferFilename(args["bufferID"]));
    killcmd = 'taskkill /f /fi "WINDOWTITLE eq nppblock_' + filename + '" /im cmd.exe'
    console.run(killcmd)

notepad.callback(fileBeforeCloseCallback, [NOTIFICATION.FILEBEFORECLOSE])

相关内容