好的,这是我实现它的方式。
Eclipse的启动系统工作如下:
1. 实现一个ILaunchConfigurationDelegate
接口,该接口中唯一的方法是launch
,它接收一个ILaunchConfiguration
、一个模式、一个ILaunch
和一个IProgressMonitor
参数。
在我的程序中,使用命令行参数使用DebugPlugin.exec()
启动一个inferiorProcess。然后通过调用DebugPlugin.newProcess()
创建一个新进程,其中包含ILaunch
、inferiorProcess、解释器名称和一些属性。此方法创建一个新的RuntimeProcess
并将其添加到ILaunch
中,反之亦然。
2. 通过使用扩展点org.eclipse.debug.core.launchConfigurationTypes
定义一个LaunchConfigurationType
,并将其添加到plugin.xml
中:
<extension
point="org.eclipse.debug.core.launchConfigurationTypes">
<launchConfigurationType
delegate="myplugin.MyLaunchConfigurationDelegate" (1)
id="myplugin.myExternalProgram" (2)
modes="run" (3)
name="MyExternalProgram" (4)
public="false"> (5)
</launchConfigurationType>
</extension>
扩展点提供了创建
ILaunchConfigurationDelegate
类的确切路径(1)和一个唯一标识符(2),用于从启动程序使用的LaunchManager中检索
ILaunchConfigurationType
实例。(3)定义它可以运行的模式,
run
和
debug
。名称(4)稍后显示在控制台视图的顶部栏中。如果您只想以编程方式访问和启动外部程序(而不是通过“运行”下拉菜单)(5)必须设置为false。
创建一个存储
IProcess
、
ILaunch
和
IStreamsProxy
实例的类,并调用适当的方法启动进程并写入streamsproxy。启动进程的方法可能如下所示:
public boolean isRunning() {
boolean result = false;
try {
if (this.process != null) {
result = true;
this.process.getExitValue();
result = false;
}
}
catch (DebugException exception) {
}
return result;
}
public void start() {
try {
if (!isRunning()) {
ILaunchConfigurationType configType = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurationType(myplugin.myExternalProgram);
ILaunchConfigurationWorkingCopy copy = configType.newInstance(null, "myExternalProgram");
this.launch = copy.launch(ILaunchManager.RUN_MODE, new NullProgressMonitor());
IProcess[] processes = this.launch.getProcesses();
if (processes.length > 0) {
this.process = this.launch.getProcesses()[0];
this.proxy = this.process.getStreamsProxy();
}
}
}
catch (CoreException exception) {
}
if (isRunning())
showConsole();
}
public void showConsole() {
if (this.process != null && this.process.getLaunch() != null) {
IConsole console = DebugUITools.getConsole(this.process);
ConsolePlugin.getDefault().getConsoleManager().showConsoleView(console);
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
IViewPart view = page.findView("org.eclipse.ui.console.ConsoleView");
if (view != null)
view.setFocus();
}
}
现在来看问题的起始点
控制台视图的IStreamsListener
监听IStreamsProxy
的OutputStreamMonitor
时无法检索,因此无法停止监听。无法防止向控制台打印。 OutputStreamMonitor
没有提供获取当前监听器的方法。无法仅仅通过子类化并覆盖/添加一些方法来解决问题,因为重要的字段和方法是私有的。
http://www.java2s.com/Open-Source/Java-Document/IDE-Eclipse/debug/org/eclipse/debug/internal/core/OutputStreamMonitor.java.htm
只需复制代码并为fListeners字段添加一个get方法,然后将某些方法的修饰符更改为public。
要将自己的OutputStreamMonitor引入系统中,您需要创建自己的IStreamsProxy。同样,仅子类化不起作用,您需要再次复制代码并进行一些更改。
http://www.java2s.com/Open-Source/Java-Document/IDE-Eclipse/debug/org/eclipse/debug/internal/core/StreamsProxy.java.htm
重要:
public class MyStreamsProxy implements IStreamsProxy, IStreamsProxy2 {
private MyOutputStreamMonitor fOutputMonitor;
private MyOutputStreamMonitor fErrorMonitor;
(...)
public MyStreamsProxy(Process process) {
if (process == null) {
return;
}
fOutputMonitor = new MyOutputStreamMonitor(process
.getInputStream());
fErrorMonitor = new MyOutputStreamMonitor(process
.getErrorStream());
fInputMonitor = new InputStreamMonitor(process
.getOutputStream());
fOutputMonitor.startMonitoring();
fErrorMonitor.startMonitoring();
fInputMonitor.startMonitoring();
}
唯一需要完成的是提供您自己的
IProcess
,该
IProcess
使用您的
IStreamsProxy
。这次,只需子类化
RuntimeProcess
并覆盖方法
createStreamsProxy()
即可:
public class MyProcess extends RuntimeProcess {
public MyProcess(ILaunch launch, Process process, String name,
Map attributes) {
super(launch, process, name, attributes);
}
@Override
protected IStreamsProxy createStreamsProxy() {
String encoding = getLaunch().getAttribute(DebugPlugin.ATTR_CONSOLE_ENCODING);
return new MyStreamsProxy(getSystemProcess());
}
}
MyProcess
是通过在 ILaunchConfigurationDelegate
的 launch 方法中创建一个新实例来集成的,而不是使用 DebugPlugin.newProcess()
。
现在可以隐藏和显示控制台视图的输出。
private IStreamListener oldListener;
protected void hideConsoleOutput() {
MyOutputStreamMonitor out
= (MyOutputStreamMonitor) this.process.getStreamsProxy().getOutputStreamMonitor();
List<IStreamListener> listeners = out.getListeners();
this.oldListener = listeners.get(0);
out.removeListener(this.oldListener);
}
protected void exposeConsoleOutput() {
MyOutputStreamMonitor out
= (MyOutputStreamMonitor) this.process.getStreamsProxy().getOutputStreamMonitor();
out.addListener(oldListener);
this.oldListener = null;
}
在添加任何其他监听器之前,必须调用hide和expose方法。可能有更好的解决方案,但这个方法可行。