You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

IntelliJ插件开发:获取OSProcessHandler执行系统命令的输出

解决方法

核心逻辑是给OSProcessHandler注册自定义的输出监听器,在输出流向控制台之前拦截捕获内容,存为字符串完成解析后,再执行控制台输出、菜单生成的后续逻辑,不要在创建handler后立刻直接绑定ConsoleView,否则无法插入自定义解析逻辑。

具体实现调整点:

  • 新增StringBuilder变量缓存进程的全量输出,可按需区分标准输出、错误输出分别存储
  • 给OSProcessHandler添加ProcessAdapter类型的监听器,重写onTextAvailable方法逐行接收输出内容,追加到缓存的StringBuilder中
  • 重写监听器的processTerminated方法,在进程执行结束后拿到完整的输出字符串,先执行自定义解析逻辑、生成对应菜单
  • 解析逻辑执行完成后,再将输出内容打印到ConsoleView;如果不需要做输出内容修改,也可以在逐行接收输出的时候同步透传给控制台,不会影响前置拦截解析的逻辑
  • 所有Swing相关的UI操作(生成菜单、操作ToolWindow/Console组件)必须切到EDT线程执行,避免UI线程阻塞异常

修改后的核心实现代码如下:

public class MyClass extends AnAction {
    private static ConsoleView view = null;
    private static ToolWindow window = null;

    @Override
    public void actionPerformed(@NotNull AnActionEvent e) {
        Project project = CommonDataKeys.PROJECT.getData(e.getDataContext());
        if (project == null)
            return;
        GeneralCommandLine generalCommandLine = new GeneralCommandLine(getAccounts());
        generalCommandLine.setCharset(Charset.forName("UTF-8"));

        OSProcessHandler processHandler = null;
        try {
            processHandler = new OSProcessHandler(generalCommandLine);
        } catch (ExecutionException ex) {
            throw new RuntimeException(ex);
        }
        
        // 初始化控制台组件
        if (view == null) {
            TextConsoleBuilderFactory factory = TextConsoleBuilderFactory.getInstance();
            TextConsoleBuilder builder = factory.createBuilder(project);
            view = builder.getConsole();
        }
        
        // 缓存进程全量输出
        StringBuilder outputCache = new StringBuilder();
        // 注册监听器拦截输出
        processHandler.addProcessListener(new ProcessAdapter() {
            @Override
            public void onTextAvailable(@NotNull ProcessEvent event, @NotNull Key outputType) {
                // 过滤系统类提示输出,可按需调整过滤规则
                if (outputType == ProcessOutputTypes.STDOUT || outputType == ProcessOutputTypes.STDERR) {
                    String text = event.getText();
                    outputCache.append(text);
                    // 实时透传输出到控制台,无感知延迟
                    view.print(text, outputType);
                }
            }

            @Override
            public void processTerminated(@NotNull ProcessEvent event) {
                String fullOutput = outputCache.toString();
                // 此处执行输出解析逻辑
                // UI操作必须切换到事件调度线程执行
                ApplicationManager.getApplication().invokeLater(() -> {
                    // 基于解析结果生成菜单的逻辑写在此处
                    // initMenuFromParseResult(fullOutput);
                    
                    // 初始化ToolWindow
                    if (window == null) {
                        ToolWindowManager manager = ToolWindowManager.getInstance(project);
                        window = manager.registerToolWindow("Cat console", true, ToolWindowAnchor.BOTTOM);
                        final ContentManager contentManager = window.getContentManager();
                        Content content = contentManager
                                .getFactory()
                                .createContent(view.getComponent(), "", false);
                        contentManager.addContent(content);
                    }
                    window.show(() -> {});
                });
            }
        });
        
        processHandler.startNotify();
    }

    private ArrayList<String> getAccounts(){
        ArrayList<String> cmds = new ArrayList<>();
        cmds.add("/usr/local/bin/getaccountscmd");
        cmds.add("ls");
        return cmds;
    }
}

如果执行的命令输出体量很大,不要等进程结束再做全量解析,可以在onTextAvailable回调里做逐行流式解析,避免StringBuilder占用过多内存,同时提升交互响应速度。

内容的提问来源于stack exchange,提问作者Lucas Kauffman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 08:36:16