UWP Console apps

In my last two blogposts, I’ve already shown some really cool features coming in the Windows Redstone 4 update. Also new in the RS4 update is the ability to create UWP Console apps! As there currently is no project template available in Visual Studio, there are a couple of things that need to be set-up manually. If, in the future, the project template becomes available, this blogpost will still give you some background information about the ‘magic’ this template will do.

Update (07/06): Microsoft has released an update to the Console UWP App project templates on the Visual Studio marketplace. Find out more here.

Create new project and throw away everything…

… well, not everything 🙂

To get started, create a new UWP project in Visual Studio.



Then, select the appropriate UWP versions (at the moment of writing this is “Windows 10 Insider Preview Build 17120”). Once that is done, you can start removing some stuff! As we are building a Console app, we don’t need App.xaml(.cs) and MainPage.xaml(.cs), just delete these 4 files. Next, we need to add a new file: Program.cs. As a result, your project will look something like this:



Add DISABLE_XAML_GENERATED_MAIN Compilation Symbol

In the Properties window of our UWP app, we need to add DISABLE_XAML_GENERATED_MAIN to the Conditional Compilation Symbols. This prevents the build system from generating the default Main method. But how will our UWP start without a Main method? Simple, we are going to write our own!

Start building

In this newly created Program class, we are going to add a Main method:

Main method namespace UwpConsole { class Program { static void Main(string[] args) { } } } 1 2 3 4 5 6 7 8 9 namespace UwpConsole { class Program { static void Main ( string [ ] args ) { } } }

Looks a lot like your classic Windows Console applications, doesn’t it? 🙂 Well, just like in your classic console applications, this is going to be our entry point. We now only need to hint Windows where it can find this Main method. For this, we need to open the Package.appxmanifest file.

To begin with, we need to add two extra namespaces: xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5" and xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"

Additional namespaces <Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5" xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4" IgnorableNamespaces="uap mp desktop4 uap5"> 1 2 3 4 5 6 7 <Package xmlns = "http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns : mp = "http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns : uap = "http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns : uap5 = "http://schemas.microsoft.com/appx/manifest/uap/windows10/5" xmlns : desktop4 = "http://schemas.microsoft.com/appx/manifest/desktop/windows10/4" IgnorableNamespaces = "uap mp desktop4 uap5" >

Now, we can start using these namespaces in our appxmanifest. Next, we need to tell that this app will run in the console (and can run in multiple instances). This can be done by adding the following attributes to the Application element: desktop4:Subsystem="console" desktop4:SupportsMultipleInstances="true" . Also we need point the EntryPoint attribute to the class, containing our Main method. So in the end, the entire Application tag will look something like this:

Updated Application tag <Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="UwpConsole.Program" desktop4:Subsystem="console" desktop4:SupportsMultipleInstances="true"> 1 2 3 4 5 <Application Id = "App" Executable = "$targetnametoken$.exe" EntryPoint = "UwpConsole.Program" desktop4 : Subsystem = "console" desktop4 : SupportsMultipleInstances = "true" >

Now, we can already run the application from Visual Studio! If everything is correct, a Console window will pop-up. Probably, the window will also immediately close, just like with classic Console applications. So let’s put some code in our Main method:

Main method static void Main(string[] args) { Console.WriteLine("Hello UWP Console!"); Console.ReadKey(); } 1 2 3 4 5 static void Main ( string [ ] args ) { Console . WriteLine ( "Hello UWP Console!" ) ; Console . ReadKey ( ) ; }

Cool! Our first UWP Console app! And just like you would expect: if you add ‘Command Line Arguments’ to your Start options (right-click your project -> properties -> Debug), you’ll get them in your Main method through the args parameter!

But wait, there’s more!

Now we have an app that can be launched just like a regular UWP app, but instead of showing a UI, a console window opens up. That’s cool, but wouldn’t it be great if we could run our console app from, well…, the console itself?

In order to accomplish this, we need to add an AppExecutionAlias to the Appxmanifest file:

appExecutionAlias <Extensions> <uap5:Extension Category="windows.appExecutionAlias" Executable="UwpConsole.exe" EntryPoint="UwpConsole.Program"> <uap5:AppExecutionAlias desktop4:Subsystem="console"> <uap5:ExecutionAlias Alias="UwpConsole.exe" /> </uap5:AppExecutionAlias> </uap5:Extension> </Extensions> 1 2 3 4 5 6 7 8 9 10 <Extensions> <uap5:Extension Category = "windows.appExecutionAlias" Executable = "UwpConsole.exe" EntryPoint = "UwpConsole.Program" > <uap5:AppExecutionAlias desktop4 : Subsystem = "console" > <uap5:ExecutionAlias Alias = "UwpConsole.exe" /> </uap5:AppExecutionAlias> </uap5:Extension> </Extensions>

The Alias that you provide in the ExecutionAlias element, is the alias that you will be able to use from the console:

FYI: If you go to Settings in Windows and select Apps, there’s this link ‘Manage app execution aliases’. If you click this link, you’ll get an overview of all apps that have an alias registered on your system:

Let’s do something cool!

Now that we got our very basic app running, let’s talk to a UWP api from it. How about triggering a toast notification from the console?

Sending toast notification from the console static void Main(string[] args) { string content, title; if (args.Length == 2) { title = args[0]; content = args[1]; } else { Console.Write("

Please enter the content for you notification: "); content = Console.ReadLine(); Console.Write("Please enter the title for your notification: "); title = Console.ReadLine(); } Console.Write("

Sending notification..."); ToastNotifier notifier = ToastNotificationManager.CreateToastNotifier(); XmlDocument toastXDoc = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02); XmlNodeList toastNodes = toastXDoc.GetElementsByTagName("text"); toastNodes.Item(0).AppendChild(toastXDoc.CreateTextNode(title)); toastNodes.Item(1).AppendChild(toastXDoc.CreateTextNode(content)); IXmlNode toastNode = toastXDoc.SelectSingleNode("/toast"); XmlElement audioElem = toastXDoc.CreateElement("audio"); audioElem.SetAttribute("src", "ms-winsoundevent:Notification.Reminder"); ToastNotification toast = new ToastNotification(toastXDoc); notifier.Show(toast); Console.WriteLine("Notification sent!"); Console.ReadKey(); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 static void Main ( string [ ] args ) { string content , title ; if ( args . Length == 2 ) { title = args [ 0 ] ; content = args [ 1 ] ; } else { Console . Write ( "

Please enter the content for you notification: " ) ; content = Console . ReadLine ( ) ; Console . Write ( "Please enter the title for your notification: " ) ; title = Console . ReadLine ( ) ; } Console . Write ( "

Sending notification..." ) ; ToastNotifier notifier = ToastNotificationManager . CreateToastNotifier ( ) ; XmlDocument toastXDoc = ToastNotificationManager . GetTemplateContent ( ToastTemplateType . ToastText02 ) ; XmlNodeList toastNodes = toastXDoc . GetElementsByTagName ( "text" ) ; toastNodes . Item ( 0 ) . AppendChild ( toastXDoc . CreateTextNode ( title ) ) ; toastNodes . Item ( 1 ) . AppendChild ( toastXDoc . CreateTextNode ( content ) ) ; IXmlNode toastNode = toastXDoc . SelectSingleNode ( "/toast" ) ; XmlElement audioElem = toastXDoc . CreateElement ( "audio" ) ; audioElem . SetAttribute ( "src" , "ms-winsoundevent:Notification.Reminder" ) ; ToastNotification toast = new ToastNotification ( toastXDoc ) ; notifier . Show ( toast ) ; Console . WriteLine ( "Notification sent!" ) ; Console . ReadKey ( ) ; }



You can find this code on GitHub.

Another example of a UWP Console app can be found in this blogpost. In this post we use a UWP Console app that does image classification using WinML.

That’s it

Yet another cool new UWP thing coming to RS4! Curious to see what tools or other stuff you guys will be building and publishing through the store! Or maybe some awesome text-based adventure game? (I’d pay for that 😉 )

Share this: Twitter

Facebook

Print

More

LinkedIn

Reddit



Tumblr

Pocket





Like this: Like Loading...