【问题标题】:Send ExitCode to an attached CMD from a WinForm?从 WinForm 将 ExitCode 发送到附加的 CMD?
【发布时间】:2013-07-26 03:31:57
【问题描述】:

我有一个 WinForm 应用程序,它将一种文件格式转换为另一种文件格式。

我想添加 CLI 支持,因此我正在使用 WindowsForms 中的 CMD。

如果从 CMD 调用应用程序,则该 CMD 将附加到 APP 并且不显示 GUI。

我的应用程序先检测文件格式,然后什么都不做。

问题是,例如,如果我运行此批处理命令,则文件将被删除,因为我没有发送错误代码:

MyApp.exe "File With Incorrec tFormat" && Del "File With Incorrect Format"

PS:“&&”批处理运算符用于检查前面命令的%ERRORLEVEL%是否为“0”以继续执行命令连接。

我想避免使用我的应用时的风险。

那么当我的应用检测到文件格式不正确时,如何向附加的 CMD 发送非零退出代码?

PS:我不知道我需要的是发送非零退出代码还是需要做其他事情。

这是过程:

' Parse Arguments
Private Sub Parse_Arguments()

    If My.Application.CommandLineArgs.Count <> 0 Then NativeMethods.AttachConsole(-1) Else Exit Sub

    Dim File As String = My.Application.CommandLineArgs.Item(0).ToLower

    If IO.File.Exists(File) Then

        If Not IsRegFile(File) Then
            Console.WriteLine("ERROR: " & "" & File & "" & " is not a valid Regedit v5.00 script.")
            End
        End If

        Dim fileinfo As New IO.FileInfo(File)

        If My.Application.CommandLineArgs.Count = 1 Then

            Try
                IO.File.WriteAllText(fileinfo.DirectoryName & ".\" & fileinfo.Name.Substring(0, fileinfo.Name.LastIndexOf(".")) & ".bat", Reg2Bat(File), System.Text.Encoding.Default)
            Catch ex As Exception
                Console.WriteLine(ex.Message)
            End Try

        Else

            Try
                IO.File.WriteAllText(My.Application.CommandLineArgs.Item(1), Reg2Bat(File), System.Text.Encoding.Default)
            Catch ex As Exception
                Console.WriteLine(ex.Message)
            End Try

        End If ' My.Application.CommandLineArgs.Count = 1

        ' Console.WriteLine("Done!")

    Else

        Console.WriteLine("ERROR: " & "" & File & "" & " don't exists.")

    End If ' IO.File.Exists

    End

End Sub

更新:

另一个更具体地说明我正在尝试做的例子...:

Public Class Form1

<System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError:=True)> _
Private Shared Function AttachConsole(dwProcessId As Int32) As Boolean
End Function

Private Shared Function SendExitCode(ByVal ExitCode As Int32) As Int32
    ' Here will goes unknown stuff to set the attached console exitcode...
    Console.WriteLine(String.Format("Expected ExitCode: {0}", ExitCode))
    Return ExitCode
End Function

Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown
    AttachConsole(-1) ' Attaches the console.
    SendExitCode(2) ' Send the exitcode (2) to the attached console.
    Application.Exit() ' ...And finally close the app.
End Sub

End Class

我该怎么做?

【问题讨论】:

    标签: vb.net winforms cmd console-application exit-code


    【解决方案1】:

    如果我正确理解了您的问题,以下代码应该可以做到。您可以从批处理文件中调用 GUI 应用程序,附加到(CMD 进程的)父控制台并向其返回退出代码。

    using System;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    namespace TestApp
    {
        static class Program
        {
            [DllImport("kernel32.dll", SetLastError = true)]
            static extern bool AttachConsole(uint dwProcessId);
            const uint ATTACH_PARENT_PROCESS = uint.MaxValue;
    
            // The main entry point for the application.
            [STAThread]
            static int Main(string[] args)
            {
                if (args.Length < 1)
                    return 1;
    
                int exitCode = 0;
                int.TryParse(args[0], out exitCode);
                var message = String.Format("argument: {0}", exitCode);
    
                if (args.Length > 1 && args[1] == "-attach")
                    AttachConsole(ATTACH_PARENT_PROCESS);
    
                Console.WriteLine(message); // do the console output 
                MessageBox.Show(message); // do the UI
    
                return exitCode;
            }
        }
    }
    

    这是一个测试批处理文件:

    @echo off
    TestApp.exe 1 -attach && echo success
    echo exit code: %errorlevel%
    

    输出:

    argument: 1
    exit code: 1
    

    将批处理文件中的“1”改为“0”,输出为:

    argument: 0
    success
    exit code: 0
    

    希望这会有所帮助。

    更新:

    在您更新的 VB 代码中,您可能需要在退出应用程序之前设置Environment.ExitCode

    Private Shared Function SendExitCode(ByVal ExitCode As Int32) As Int32
        ' Here will goes unknown stuff to set the attached console exitcode...
        Console.WriteLine(String.Format("Expected ExitCode: {0}", ExitCode))
    
        Environment.ExitCode = ExitCode
    
        Return ExitCode
    End Function
    

    【讨论】:

    • 谢谢,但我正在使用 VB.NET,我尝试使用在线翻译器和我自己进行翻译,但在 VB 上不起作用,我不知道我缺少什么你的代码,你能帮我翻译一下吗?我已经在我的更新中发布了我的翻译意图,请看。
    • 无法在此处发布格式良好的代码,因此将其附加到我的答案中。
    • 最后我所做的是使用“Environment.Exit()”(不是 .exitcode),它不需要附加任何控制台,谢谢大家...
    • 很高兴你解决了。附带说明一下,如果您不从 GUI 应用程序(使用 Console.Write)执行任何控制台输出,则不必附加到父控制台。控制台无论如何都与退出代码无关。但是,如果您的 GUI 应用程序是从批处理文件调用的,并且您确实使用 Console.Write 而不连接到父控制台,则输出将丢失。
    【解决方案2】:

    您需要将您的应用程序编译为控制台应用程序(即使您有一个如果没有从命令行调用就启动的 GUI)并且有一个返回 int 或调用 environment.exit(-1) 的 main 方法.

    【讨论】:

    • 感谢您的帮助,我已经尝试过并且可以工作,但是正如我所说的,我在 windowsForm 上,如果我编译为“控制台应用程序”,那么当我启动时会显示一个令人作呕的控制台实例GUI 因此,如果您知道如何避免在我从资源管理器启动我的应用程序时不自动连接该控制台,那么我会非常感激它......这就是为什么我不编译为控制台应用程序,我想要控制台仅在我从控制台运行程序时显示,我尝试使用 Freeconsole APi 功能在启动时从 GUI 释放控制台,但什么也不做。
    猜你喜欢
    • 1970-01-01
    • 2014-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多