【问题标题】:Executed vbscript with C# returns wrong exit code使用 C# 执行的 vbscript 返回错误的退出代码
【发布时间】:2015-05-21 21:22:24
【问题描述】:

我在用 C# 执行 vbscript 时遇到了一个大问题。 我有这个通用的流程执行功能:

/// <summary>
/// Runs a process silent (Without DOS window) with the given arguments and returns the process' exit code.
/// </summary>
/// <param name="output">Recieves the output of either std/err or std/out</param>
/// <param name="exe">The executable to run, may be unqualified or contain environment variables</param>
/// <param name="args">The list of unescaped arguments to provide to the executable</param>
/// <returns>Returns process' exit code after the program exits</returns>
/// <exception cref="System.IO.FileNotFoundException">Raised when the exe was not found</exception>
/// <exception cref="System.ArgumentNullException">Raised when one of the arguments is null</exception>
/// <exception cref="System.ArgumentOutOfRangeException">Raised if an argument contains '\0', '\r', or '\n'</exception>
public static int Run(Action<string> output, string exe, params string[] args)
{
    if (String.IsNullOrEmpty(exe))
        throw new FileNotFoundException();
    if (output == null)
        throw new ArgumentNullException("output");

    ProcessStartInfo psi = new ProcessStartInfo();
    psi.UseShellExecute = false;
    psi.RedirectStandardError = true;
    psi.RedirectStandardOutput = true;
    psi.RedirectStandardInput = true;
    psi.WindowStyle = ProcessWindowStyle.Hidden;
    psi.CreateNoWindow = true;
    psi.ErrorDialog = false;
    psi.WorkingDirectory = Environment.CurrentDirectory;
    psi.FileName = FindExePath(exe);
    psi.Arguments = args[0];

    using (Process process = Process.Start(psi))
    using (ManualResetEvent mreOut = new ManualResetEvent(false),
    mreErr = new ManualResetEvent(false))
    {
        process.OutputDataReceived += (o, e) => { if (e.Data == null) mreOut.Set(); else output(e.Data); };
        process.BeginOutputReadLine();
        process.ErrorDataReceived += (o, e) => { if (e.Data == null) mreErr.Set(); else output(e.Data); };
        process.BeginErrorReadLine();

        process.WaitForExit();

        mreOut.WaitOne();
        mreErr.WaitOne();
        return process.ExitCode;
    }
}

像魅力一样工作。 现在我想用这个函数执行一个 vbscript。 我这样称呼它:

int exit_code = ProcessUtility.Run(output_action, "cscript.exe", "//Nologo" + save_parameter_string);

这也运行得很好,但我的问题是,它运行得有点好。 如果我执行包含错误的 vbscript,则退出代码也是“0”;( 在我的例子中,输出包含来自 vbscript 的正确“异常”: “...\test.vbs(145, 12) Microsoft VBScript 中的运行时错误:需要对象” 但是退出码是0。

有人知道吗,为什么?

【问题讨论】:

    标签: c# vbscript


    【解决方案1】:

    或者,您可以使用On Error Resume Next 中所述的VBScript -- Using error handling 技术。

    简而言之,将您的原始脚本包装在此类“异常处理程序”中:

    On Error Resume Next
    
    YourOriginalUnsafeCode()
    
    ' This would make cscript return non-zero in case of error'
    if err.number <> 0 then WScript.quit err.number
    
    Sub YourOriginalUnsafeCode()
        ' Your original code goes into this function'
        a = 1 / 0
        a = 2
    End Sub
    

    【讨论】:

    • 这是否会为YourOriginalUnsafeCode 中的所有类型的错误(包括语法问题)提供错误检测处理,无论它们发生在其中吗?
    【解决方案2】:

    我把它放在一个 BAT 文件中以生成运行时错误:

    echo x = 1/0 > foo.vbs
    cscript foo.vbs
    echo %ERRORLEVEL%
    

    输出:

    C:\null\foo.vbs(1, 1) Microsoft VBScript runtime error: Division by zero
    
    0
    

    退出代码是0,因此您无法使用退出代码检测运行时错误。

    (%ERRORLEVEL%1 仅用于语法错误 (echo x = ?1/0 &gt; foo.vbs))

    您需要解析输出或确定 StdErr 的行为,或者您可以通过 ScriptControl 从 .Net 运行 VBScript,这会生成标准异常:How to execute VBScript command within textbox from C# application?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-20
      • 1970-01-01
      相关资源
      最近更新 更多