1

I have written some applications of type Windows Forms Application (GUI apps) and those applications can be launched/called from console instead of use the graphical interface, I mean it can be used both as GUI or as CLI.

The problem that I always have seen in this kind of "hybrid" apps is that a WinForms application that has CLI supports it takes a lot more time to initialize when the app is called from the CMD than a normal Console Application, I suppose that this is because the need to load the (GUI) form.

...So, I would like to speed up the initialization/startup of my winforms apps when are used directly from the commandline.

At the moment I'm doing it through the Application.Startup event, but I would like to know if there is a more friendly way to avoid/suspend the Load event of the form when the alternative usage of the application tells that is not required to load a form because the app is gonna be used from the console.

To understand better my problem I will share some images...

This is the Graphical User Interface on my application:

enter image description here

And this is the Command-line Interface:

enter image description here

When the program is called from the console it takes a lot of time to show the displayed console help because the application loads the form.

BUT AS I SAID I SOLVED THIS ISSUE BY USING THE APPLICATION.STARTUP EVENT:

Imports Reg2Bat.Main

Namespace My

    Partial Friend Class MyApplication

        Private Sub CLI() Handles MyBase.Startup

            ' Call the method that parses the CLI arguments (if any),
            ' this is done before loading the form to speed up the CLI startup.
            ParseCLIArguments()

        End Sub

    End Class

End Namespace

...I just would like to know if exists a better way to avoid the form load event without touching the application events.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
ElektroStudios
  • 19,105
  • 33
  • 200
  • 417
  • 1
    What do you mean by "better?" Seems like this solves it pretty well. In any case, what prevents you from simply avoiding the Form instantiation in `Main()`? – Robert Harvey Jan 28 '14 at 17:34
  • @Robert Harvey in other words I would like to know if this is possible to do it through the main application class (See: Imports Reg2Bat.Main) where are written all the Form eventhandlers and almost all the code. – ElektroStudios Jan 28 '14 at 17:37
  • Every Winforms application I've ever seen has some code in the `Main()` method that instantiates a form. Just prevent that code from running. – Robert Harvey Jan 28 '14 at 17:39
  • @Robert Harvey but the "Main" method is for Console applications, I'm using a winform GUI. – ElektroStudios Jan 28 '14 at 17:40
  • `Sub Main` is available (complete with commandline args) for WinForms as well. – Ňɏssa Pøngjǣrdenlarp Jan 28 '14 at 17:41
  • @Plutonix I'm testing to add a "Main" method to show a msgbox and nothing happens... – ElektroStudios Jan 28 '14 at 17:42
  • Do a search for "public static void Main" in Visual Studio. You will find the Main() method. In there, you will see that it `new`s up a form. Did you find it? – Robert Harvey Jan 28 '14 at 17:42
  • 1
    If you set the project startup method to `Sub Main` instead of FormX a static `Sub Main` (in a module) will run. You can write it as `Sub Main(argv As String())` to grab the commandline already parsed there. Presumably, if there **IS** a command line, you can go the CLI route, else instance and start in WinForms mode. as per earlier http://stackoverflow.com/a/20301831/1070452 – Ňɏssa Pøngjǣrdenlarp Jan 28 '14 at 17:46
  • @Plutonix thanks this has more advantages for me than using the startup event, you can post that solution in an answer if you want I will mar kit as accepted. – ElektroStudios Jan 28 '14 at 18:03
  • I get slow loading on winforms the first time the GAC is loaded into memory, but faster loading on subsequent runs as the global assembly is already cached. Or are we talking about something eles ? – Knuckle-Dragger Jan 29 '14 at 09:26

2 Answers2

3

If you set the project startup method to Sub Main instead of FormX a static Sub Main (in a module) will run. You can write it as:

 Sub Main(argv As String()) 

to grab the commandline already parsed there. Presumably, if there IS a command line, you can go the CLI route, else instance and start in WinForms mode.

Public Sub Main(argv As String())
    If argv.Length >0 Then
        ' parse and run CLI mode (?)
    Else
        Application.EnableVisualStyles
        Application.Run(new FormMain)
    End If
End Sub

See also: https://stackoverflow.com/a/20301831/1070452

Ňɏssa Pøngjǣrdenlarp
  • 38,411
  • 12
  • 59
  • 178
1

Alternative solution as said by @Plutonix:

At the project properties page uncheck "Enable application framework" to be able to load a Winforms (GUI) app from a module, otherwise I can't select any Main sub from a module.

And then write a module with the desired instructions to perform...for example:

''' <summary>
''' The CLI Class where are defined the CLI methods and other CLI things.
''' </summary>
Module CLI

    ''' <summary>
    ''' Defines the entry point of the application.
    ''' </summary>
    Public Sub Main()

        If My.Application.CommandLineArgs.Count <> 0 Then

            ' Attach the console.
            NativeMethods.AttachConsole(-1)

            ' Call the method that parses the CLI arguments (if any),
            ' this is done before loading the GUI form to speed up the CLI startup.
            ParseCLIArguments()

        Else

            ' Any argument was passed so I show the GUI form.
            GUI.ShowDialog()

        End If

    End Sub

''' <summary>
''' Parses the Command-Line arguments.
''' </summary>
Private sub ParseCLIArguments
    ...
End Sub

End Module
ElektroStudios
  • 19,105
  • 33
  • 200
  • 417