【问题标题】:Calling an external application (i.e. Windows Calculator) in a GWT web application在 GWT Web 应用程序中调用外部应用程序(即 Windows Calculator)
【发布时间】:2014-03-05 20:32:30
【问题描述】:

当用户单击 GWT Web 应用程序中的按钮时,我正在尝试调用外部 Windows 应用程序(即 calc.exe)。有没有办法做到这一点?

以下是我到目前为止已经尝试过的:

1.) 尝试了 Runtime.exec 和 ProcessBuilder 但我最终遇到了 GWT 编译错误

Runtime.exec 代码:

Process winCalc;
try {
    winCalc = Runtime.getRuntime().exec("\"C:/Windows/System32/calc.exe\"");
    winCalc.waitFor();

} catch (IOException e) {
    e.printStackTrace();
} catch (InterruptedException e) {
    e.printStackTrace();
}

Runtime.exec 代码 - GWT 编译错误:

Rebinding dir.ClientGinjector
            Checking rule <generate-with class='org.jsonmaker.gwt.rebind.JsonizerGenerator'/>
               [ERROR] Errors in 'file:/C:/Users/blahblah/framework/Toolbar.java'
                  [ERROR] Line 962: No source code is available for type java.lang.Process; did you forget to inherit a required module?
                  [ERROR] Line 964: No source code is available for type java.lang.Runtime; did you forget to inherit a required module?
                  [ERROR] Line 969: No source code is available for type java.lang.InterruptedException; did you forget to inherit a required module?
               [ERROR] Unable to find type 'dir.ClientGinjector'
                  [ERROR] Hint: Previous compiler errors may have made this type unavailable
                  [ERROR] Hint: Check the inheritance chain from your module; it may not be inheriting a required module or a module may not be adding its source path entries properly
   [ERROR] Errors in 'file:/C:/Users/blahblah/gin/ClientGinjector.java'
      [ERROR] Line 60:  Failed to resolve 'dir.ClientGinjector' via deferred binding

---

ProcessBuilder 代码:

ProcessBuilder pbWinCalc = new ProcessBuilder ("C:/Windows/System32/calc.exe");

try {
    Process pWinCalc = pbWinCalc.start();
    System.out.println("[dan]: pWinCalc.exitValue() = " + pWinCalc.exitValue());

} catch (IOException e) {
    System.out.println("[dan]: stacktrace = " + e.getMessage().toString());
}

ProcessBuilder 代码 - GWT 编译错误:

Rebinding dir.ClientGinjector
            Checking rule <generate-with class='org.jsonmaker.gwt.rebind.JsonizerGenerator'/>
               [ERROR] Errors in 'file:/C:/Users/blahblah/framework/Toolbar.java'
                  [ERROR] Line 974: No source code is available for type java.lang.ProcessBuilder; did you forget to inherit a required module?
                  [ERROR] Line 977: No source code is available for type java.lang.Process; did you forget to inherit a required module?
               [ERROR] Unable to find type 'dir.ClientGinjector'
                  [ERROR] Hint: Previous compiler errors may have made this type unavailable
                  [ERROR] Hint: Check the inheritance chain from your module; it may not be inheriting a required module or a module may not be adding its source path entries properly
   [ERROR] Errors in 'file:/C:/Users/blahblah/gin/ClientGinjector.java'
      [ERROR] Line 60:  Failed to resolve 'dir.ClientGinjector' via deferred binding

2.) 尝试按照此链接 (GWT + ProcessBuilder) 中的建议在扩展 RemoteServiceServlet 的单独类中调用 ProcessBuilder。

ProcessBuilder 代码:

import java.io.IOException;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

public class WinCalcServiceImpl extends RemoteServiceServlet {

    private static final long serialVersionUID = 7495421224005326634L;

    public void getWinCalculator(){
        //Dan - Using ProcessBuilder
        final ProcessBuilder pbWinCalc = new ProcessBuilder ("C:/Windows/System32/calc.exe");

        try {
            final Process pWinCalc = pbWinCalc.start();
            System.out.println("[dan]: pWinCalc.exitValue() = " + pWinCalc.exitValue());

        } catch (final IOException e) {
            System.out.println("[dan]: stacktrace = " + e.getMessage().toString());
        }
//      p.waitFor();
    }

}

ProcessBuilder - GWT 编译错误:

         Rebinding com.gwtplatform.dispatch.shared.DispatchService
            Invoking generator com.google.gwt.user.rebind.rpc.DlServiceInterfaceProxyGenerator
               Running DLProxyCreator
   [ERROR] An internal compiler exception occurred
com.google.gwt.dev.jjs.InternalCompilerException: Failed to get JNode
    at com.google.gwt.dev.jjs.impl.TypeMap.get(TypeMap.java:140)
    at com.google.gwt.dev.jjs.impl.TypeMap.get(TypeMap.java:71)
    at com.google.gwt.dev.jjs.impl.BuildTypeMap.getType(BuildTypeMap.java:730)
    at com.google.gwt.dev.jjs.impl.BuildTypeMap.process(BuildTypeMap.java:814)
    at com.google.gwt.dev.jjs.impl.BuildTypeMap.access$700(BuildTypeMap.java:99)
    at com.google.gwt.dev.jjs.impl.BuildTypeMap$BuildDeclMapVisitor.process(BuildTypeMap.java:325)
    at com.google.gwt.dev.jjs.impl.BuildTypeMap$BuildDeclMapVisitor.visit(BuildTypeMap.java:244)
    at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.traverse(TypeDeclaration.java:1198)
    at org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration.traverse(CompilationUnitDeclaration.java:687)
    at com.google.gwt.dev.jjs.impl.BuildTypeMap.createPeersForNonTypeDecls(BuildTypeMap.java:637)
    at com.google.gwt.dev.jjs.impl.BuildTypeMap.exec(BuildTypeMap.java:514)
    at com.google.gwt.dev.jjs.impl.BuildTypeMap.exec(BuildTypeMap.java:523)
    at com.google.gwt.dev.jjs.JavaToJavaScriptCompiler.precompile(JavaToJavaScriptCompiler.java:599)
    at com.google.gwt.dev.jjs.JavaScriptCompiler.precompile(JavaScriptCompiler.java:33)
    at com.google.gwt.dev.Precompile.precompile(Precompile.java:284)
    at com.google.gwt.dev.Precompile.precompile(Precompile.java:233)
    at com.google.gwt.dev.Precompile.precompile(Precompile.java:145)
    at com.google.gwt.dev.Compiler.run(Compiler.java:232)
    at com.google.gwt.dev.Compiler.run(Compiler.java:198)
    at com.google.gwt.dev.Compiler$1.run(Compiler.java:170)
    at com.google.gwt.dev.CompileTaskRunner.doRun(CompileTaskRunner.java:88)
    at com.google.gwt.dev.CompileTaskRunner.runWithAppropriateLogger(CompileTaskRunner.java:82)
    at com.google.gwt.dev.Compiler.main(Compiler.java:177)
      [ERROR] <no source info>: public class com.google.gwt.user.server.rpc.RemoteServiceServlet
    extends com.google.gwt.user.server.rpc.AbstractRemoteServiceServlet
    implements : com.google.gwt.user.server.rpc.SerializationPolicyProvider
/*   fields   */
private final [unresolved] java.lang.Object delegate
private final [unresolved] Map<java.lang.String,Unresolved type com.google.gwt.user.server.rpc.SerializationPolicy> serializationPolicyCache
/*   methods   */
public void <init>() 
[unresolved] public void <init>(java.lang.Object) 
[unresolved] protected void checkPermutationStrongName() throws Unresolved type java.lang.SecurityException
[unresolved] protected Unresolved type com.google.gwt.user.server.rpc.SerializationPolicy doGetSerializationPolicy(Unresolved type javax.servlet.http.HttpServletRequest, java.lang.String, java.lang.String) 
[unresolved] private Unresolved type com.google.gwt.user.server.rpc.SerializationPolicy getCachedSerializationPolicy(java.lang.String, java.lang.String) 
[unresolved] public final Unresolved type com.google.gwt.user.server.rpc.SerializationPolicy getSerializationPolicy(java.lang.String, java.lang.String) 
[unresolved] static Unresolved type com.google.gwt.user.server.rpc.SerializationPolicy loadSerializationPolicy(Unresolved type javax.servlet.http.HttpServlet, Unresolved type javax.servlet.http.HttpServletRequest, java.lang.String, java.lang.String) 
[unresolved] protected void onAfterResponseSerialized(java.lang.String) 
[unresolved] protected void onBeforeRequestDeserialized(java.lang.String) 
[unresolved] public java.lang.String processCall(java.lang.String) throws Unresolved type com.google.gwt.user.client.rpc.SerializationException
public final void processPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) throws java.io.IOException, javax.servlet.ServletException, com.google.gwt.user.client.rpc.SerializationException
[unresolved] private void putCachedSerializationPolicy(java.lang.String, java.lang.String, Unresolved type com.google.gwt.user.server.rpc.SerializationPolicy) 
[unresolved] protected boolean shouldCompressResponse(Unresolved type javax.servlet.http.HttpServletRequest, Unresolved type javax.servlet.http.HttpServletResponse, java.lang.String) 
[unresolved] private void writeResponse(Unresolved type javax.servlet.http.HttpServletRequest, Unresolved type javax.servlet.http.HttpServletResponse, java.lang.String) throws java.io.IOException



         org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding
      [ERROR] at WinCalcServiceImpl.java(7): class WinCalcServiceImpl 
         com.google.gwt.dev.jjs.ast.JClassType

【问题讨论】:

  • 我正在尝试通过从我的 web 应用程序调用现有的 Windows 计算器来重用它。我只是在想,与其为我的 web 应用程序创建一个全新的计算器程序,不如直接重用 Windows 提供的现有应用程序。有没有其他方法可以做到这一点,或者我别无选择,只能在我的 web 应用程序中创建 calc 函数?

标签: java gwt runtime.exec processbuilder


【解决方案1】:

你做不到。浏览器不允许访问用户计算机上的可执行文件。对于那里的每个黑客来说,这将是一个梦想成真。

【讨论】:

    【解决方案2】:

    一个 webapp 不应该也不能调用本地程序..

    GWT 将客户端类编译为 javascript,并且不支持 Runtime,因此 GWT 不知道如何将您的 Runtime 用法转换为 JS。

    有关 GWT 支持的类(客户端)的列表,请参阅http://www.gwtproject.org/doc/latest/RefJreEmulation.html

    【讨论】:

      【解决方案3】:

      我明白了。谢谢你们的答案。我仍然是 GWT 的新手。您的回答帮助我更多地了解 GWT 以及它如何将类编译为 javascript,以及为什么不允许 webapp 访问本地资源背后的想法。但是,我认为仍然有例外,但取决于需要和场景;就我而言,我的 webapp 仅在封闭的组/网络中使用和访问,而不是供公众/任何人使用。

      对于同样感兴趣的任何人,我所做的是我创建了一个 JavaScript 代码,它使用 ActiveXObject 实现来运行外部应用程序,在我的例子中是一个 Windows 计算器。然后使用这段代码,我在 IE 浏览器中运行它,因为只有 IE 完全支持 ActiveX 实现。

      我没有尝试过 Braj 的上述建议,但我认为这也是一种可行的替代方案。也许这个周末我会尝试使用这种方法。

      【讨论】:

        【解决方案4】:

        使用 Java Applet 在 GWT 中使用 JSNI 调用外部应用程序。

        请查看以下链接以获取示例代码。

        Invoking Applet Methods From JavaScript Code

        Call Java Applet function from Javascript

        How to call Applet method from javascript

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-11-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-02-28
          相关资源
          最近更新 更多