Creating a UWP Console app in C#


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.

Conditional compilation symbols

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)
        {
        }
    }
}

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">

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">

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();
}

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>

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("\nPlease enter the content for you notification: ");
        content = Console.ReadLine();
        Console.Write("Please enter the title for your notification: ");
        title = Console.ReadLine();
    }

    Console.Write("\nSending 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 ;-) )

Did you enjoy reading this? If my work has saved you time or taught you something new, consider buying me a coffee.

Join the discussion

Archived comments (12)

Archived comments from the original blog, preserved here for reference. Join the discussion above.

  1. Ezra
    Thanks so much for these instructions! I built a little UWP console app to update a file for myself, and it works fine as long as I build/run in the debug configuration. If I try to run it after building in the release configuration, the app wont launch. Any thoughts on why that might be the case?
  2. PieEatingNinjasauthorIn reply
    Glad you like it! Concerning your problem, you might take a look at differences between your debug and release configuration. If you can't find it out, please provide me your Solution so I could take a look at it, if you want.
  3. PapaIn reply
    Ezra - Same thing here, but it works after unchecking "Compile with .NET Native tool chain" in project Properties/Build. PieEatingNinjas - I have a couple different questions to add: The console app comes up after the usual default Windows app window.. can that be skipped so only a console app runs? And there is a Windows Store app activation error after the console+window are closed.. can that be oppressed? ["Compile with .NET Native tool chain" being a store requirement, why bother..?] BTW, same behaviors with your GitHub project. Barring those minor issues this is undoubtedly a good testing tool for libraries, OAuth2 redirect (per custom app URIs, otherwise out-of-reach for normal console apps), etc.
  4. PapaIn reply
    Hello - Initially I got this working despite being on too old of a version of Windows 10, however that produced an extra non-console window to appear and an "..unable to activate.." error. Those problems went away as soon as I updated to 1803. Since the issue Ezra saw (Release not working) only seems to be remedied by unchecking "Compile with .NET Native tool chain", is it a forgone conclusion that console UWP apps cannot be sold @ the store?
  5. EzraIn reply
    Check out my comment above about there being a template from which to build the C# UWP console apps now. Fingers crossed it fixes this issue.
  6. EzraIn reply
    Thanks for the reply! I'll take a look again after I follow these directions to put the app back together. Maybe the template will solve the problem. https://blogs.windows.com/buildingapps/2018/06/06/c-console-uwp-applications/#lx6114BhGKvLgCmi.97
  7. Mark Pflug
    Nice walk-through. You might clarify the "we need to add an AppExecutionAlias to the Appxmanifest file" with some context about where it needs to be added. I had to go look at the github project to figure that part out.
  8. John Smith
    Exactly what is was looking for. Suggestion, post full sample code on github
  9. PieEatingNinjasauthorIn reply
    Hi John, The code is already available on GitHub (https://github.com/PieEatingNinjas/UwpConsoleApp/tree/master). Did you miss this or do you have a remark about the source code itself?
  10. Bluetooth GATT server.
    […] In general, UWP programs are desktop GUI applications, but with small tricks console application can be developed also. You can find all the information how to do it here: https://blog.pieeatingninjas.be/2018/04/05/creating-a-uwp-console-app-in-c/. […]
  11. Václav
    Hi, still useful this information. Thank you