Vb.net 是否从WinForm将ExitCode发送到附加的CMD?

Vb.net 是否从WinForm将ExitCode发送到附加的CMD?,vb.net,winforms,cmd,console-application,exit-code,Vb.net,Winforms,Cmd,Console Application,Exit Code,我有一个WinForm应用程序,它包括将一种fle格式转换为另一种文件格式 我想添加CLI支持,所以我正在使用WindowsForms中的CMD 如果从CMD调用应用程序,则该CMD将附加到应用程序,并且GUI不会显示 我的应用程序首先检测文件格式 例如,如果我运行此批处理命令,则文件将被删除,因为我没有发送错误代码: MyApp.exe "File With Incorrec tFormat" && Del "File With Incorrect Format" PS:“&

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

我想添加CLI支持,所以我正在使用WindowsForms中的CMD

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

我的应用程序首先检测文件格式

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

MyApp.exe "File With Incorrec tFormat" && Del "File With Incorrect Format"
PS:“&&”批处理运算符用于检查before命令的%ERRORLEVEL%是否为“0”,以继续进行命令连接

我想在使用我的应用程序时避免这样的风险

那么,当我的应用程序检测到文件格式不正确时,我如何向附加的CMD发送非零exitcodes

PS:我不知道我需要的是发送一个非零exitcode还是我需要做其他事情

这是程序:

' 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
分析参数 私有子解析_参数() 如果My.Application.CommandLineArgs.Count为0,则NativeMethods.AttachConsole(-1)否则退出Sub Dim文件格式为String=My.Application.CommandLineArgs.Item(0).ToLower 如果IO.File.Exists(文件)存在,则 如果不是IsRegFile(文件),则 Console.WriteLine(“错误:&”“文件&”“不是有效的Regedit v5.00脚本。”) 终止 如果结束 将fileinfo设置为新IO.fileinfo(文件) 如果My.Application.CommandLineArgs.Count=1,则 尝试 IO.File.writealText(fileinfo.DirectoryName&“\”&fileinfo.Name.Substring(0,fileinfo.Name.LastIndexOf(“.”)和“.bat”,Reg2Bat(文件),System.Text.Encoding.Default) 特例 控制台写入线(例如消息) 结束尝试 其他的 尝试 IO.File.WriteAllText(My.Application.CommandLineArgs.Item(1)、Reg2Bat(文件)、System.Text.Encoding.Default) 特例 控制台写入线(例如消息) 结束尝试 如果'My.Application.CommandLineArgs.Count=1,则结束 'Console.WriteLine(“完成!”) 其他的 Console.WriteLine(“错误:&”“文件&”“不存在”) 如果“IO.File.exe”存在,则结束 终止 端接头 更新:

另一个更具体的例子是我正在尝试做什么…:

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
公共类表单1
_
专用共享函数AttachConsole(dwProcessId为Int32)为布尔值
端函数
私有共享函数SendExitCode(ByVal ExitCode作为Int32)作为Int32
'这里将使用未知内容来设置连接的控制台exitcode。。。
Console.WriteLine(String.Format(“预期的ExitCode:{0}”,ExitCode))
返回退出码
端函数
显示的私有子表单1_(发送方作为对象,e作为事件参数)处理MyBase。显示
AttachConsole(-1)”连接控制台。
SendExitCode(2)'将exitcode(2)发送到连接的控制台。
Application.Exit()“…并最终关闭应用程序。
端接头
末级

如何操作?

您需要将应用程序编译为控制台应用程序(即使您有一个GUI,如果没有从命令行调用它,您也可以启动该GUI),并且有一个返回int或call环境的main方法。退出(-1)。

您需要将应用程序编译为控制台应用程序(即使您有一个GUI,如果不是从命令行调用,您也可以启动它),并且有一个main方法返回int或call environment.exit(-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;
        }
    }
}
输出:

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

argument: 0
success
exit code: 0
希望这有帮助

更新:

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

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

如果我正确理解了您的问题,下面的代码应该可以做到。您可以从批处理文件调用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;
        }
    }
}
输出:

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

argument: 0
success
exit code: 0
希望这有帮助

更新:

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

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

谢谢你的asnwer,我已经尝试过了,而且很有效,但是正如我所说的,我使用的是windowsForm,如果我编译为“控制台应用程序”然后,当我启动GUI时,会显示一个令人恶心的控制台实例,因此如果您知道如何避免在我从explorer启动应用程序时控制台不会自动连接,那么我将非常感激它…这就是为什么我不编译为控制台应用程序,我希望仅当我从控制台运行程序时才显示控制台,我已尝试使用Freecon唯一的APi函数在开始时从GUI中释放控制台,但什么也不做。感谢asnwer,我已经尝试过了,并且可以工作,但是正如我所说的,如果我编译为“控制台应用程序”,我就在windowsForm上然后,当我启动GUI时,会显示一个令人恶心的控制台实例,因此如果您知道如何避免在我从explorer启动应用程序时控制台不会自动连接,那么我将非常感激它…这就是为什么我不编译为控制台应用程序,我希望仅当我从控制台运行程序时才显示控制台,我已尝试使用Freecon唯一的APi函数在开始时从GUI中释放控制台,但什么也不做。谢谢,但我正在使用VB.NET,我曾尝试使用在线翻译工具翻译它,但我自己在VB上不工作,我不知道你的代码中缺少了什么,你能帮我翻译吗?我已经在更新中发布了我的翻译意图,请参见。C我不会在这里发布格式很好的代码,所以将其附加到我的答案中。最后,我所做的是使用“Environment.Exit()”(not.exitcode),它不需要附加任何控制台,谢谢大家…很高兴您已经解决了这个问题。顺便说一句,如果您不从GUI执行任何控制台输出,您就不必附加到父控制台