Open shaggygi opened 4 years ago
This is right in @Keboo's wheelhouse.
@shaggygi what kind of support or integration were you wanting to see? To some degree there is already support (simple example here).
There are a few key details to be aware of:
@Keboo thanks for response. I believe your example link will work for me. I'll try it out soon.
While I have not thought it out completely, I was mainly wanting to have the ability to 1) call the WPF EXE and run normally (displaying UI and such) and 2) interact with the WPF EXE in a console to see parameters/help/results like you would with this API and Console-type app. Thx
@Keboo (and others), you might be interested in this solution that I finally put on out SO. @jonsequitur and I have talked about it offline before. While it's currently Windows-specific, I don't see why it has to be. This approach allows a winexe to operate as normal (e.g. with a hidden window), which is usually important; especially for apps that typically shouldn't have a console (ex: Windows service). However, if any command-line arguments are specified then you're in Console Mode. For a single command, you just run and exit. In an existing console, you take over and then relinquish it back when you're done. I didn't have a need for an interactive CLI, but I think it could be adapted to support that. Ultimately, this takes the reverse approach so that you only have the console window when it's necessary instead of all the time.
It'd be interesting to genericize this behavior and make it something that could easily be turned on or off. Nicer still would be if we actually had a compile target to handle this bootstrapping automatically (e.g. <OutputType>dualexe</OutputType>
or something).
I currently use it like this:
App.xaml.cs
protected override void OnStartup(StartupEventArgs e)
{
// initalization here
// at bottom of method
var command = new RootCommand("SmartCardSolution")
{
new Option<StartPage>(
new []{"--page", "-p"},
() => StartPage.Admin,
"The page that should be visible on startup.")
};
command.Handler = CommandHandler.Create((StartPage page) =>
{
switch (page)
{
case StartPage.Admin:
ExecuteAdmin();
return 0;
default:
return 1;
}
});
var exitCode = command.InvokeAsync(e.Args).GetAwaiter().GetResult();
Shutdown(exitCode);
}
However, when executing the application with the --help
or --version
parameters, I don't get any console output.
I, too, wish to use this with WPF and WinForms apps.
However, the functionality I need is just displaying the help (and to a lesser extent version) information when those switches are used from the command line; in my roll-your-own apps in the past, I got this to work simply by calling AttachConsole (AttachParentProcess) before outputting the help text.
Is there a convenient hook or place I could intercept --help and --version usage in order to make that call?
@cerebrate I don't have enough context. Right now those are implemented in middleware so when the parser or command is invoked, and those are present, they short circuit the command handler and write to the current IConsole
. You could certainly provide an IConsole
and call the invocation yourself, which is what our tests do using the TestConsole
class. I could provide a more useful answer I think if I understood more about what you're currently doing.
The primary issue I see with using the library with a WPF app, is with how Windows does output redirection. To avoid showing terminal windows every time a WPF app is launched, the Console.Out
gets redirected. This is why things like --help
and --version
do not appear to work. Within your application this library is simply outputting that information to the default IConsole
implementation (which just uses Console.Write
). The hard part here is separating the difference between the applications being started normally, and the application being started from a command line invocation. Given that, I don't think there is much this library can do to address the WPF limitation..
With all of that said I did update my example app to use the Kernel32 AttachConsole
method. This now properly shows help and version when they are passed.
@jonsequitur
The immediate context is that I have a utility (Mouse Jiggler), which is a Windows application, but which takes a variety of command-line parameters to allow manual override of various settings on startup (which would usually be used in the launching shortcut). However, since it can be launched from the command-line as well, I would like to let parameter errors (specifying an invalid jiggle period, for example), requests for help, etc., to show when this is the case - so that people can try out command-line parameters, refresh their memory of them, etc., easily.
In the old version of Mouse Jiggler, when I was rolling my own command-line parsing, I just called AttachConsole at the top of my PrintHelpText method, thus ensuring that if it was launched from a console session it would re-redirect output to that session's console. That's basically what I want to achieve here.
I can get what I want in the present just by wrapping the entire invoking of the command line in an AttachConsole / FreeConsole pair, since it does not appear to have harmful side effects when the parent is not a console app (e.g., it's started from a shortcut), but that seems inelegant. It would seem better to me if there were some hook that could be used to call them only when actually needed.
It would be nice to use this API with WPF (and future WinUI) apps to parse out arguments. I have created basic apps that do this, within the App.xaml.cs file, but would probably be better if there was support from here.