Develop & Publish .NET MAUI Application for Windows using Visual Studio Code
Tags: dotnet, maui, windows, publish
Published: 2023-11-25 16:42:44

Hello Developers,

=> So today we are developing a basic app using .NET maui framework & we'll publish it for the Windows platform.

=> .NET MAUI, which stands for .NET Multi-platform App UI, is an open-source, cross-platform framework for building native mobile and desktop applications. It is an evolution of the Xamarin.Forms framework and is part of the broader .NET ecosystem.

Before we start our work , let's install required tools.

**Step - 1 : Installation task** 

 - [dotnet SDK (Recommend : SDK 7.0)](https://dotnet.microsoft.com/en-us/download) 
 - [dotnet Runtime (Recommend : 7.0)](https://dotnet.microsoft.com/en-us/download/dotnet/7.0) 
 - [Visual Studio Code](https://code.visualstudio.com/download)
 
-> Add required Extensions in vs code
 - C# (by Microsoft)
 - .NET Runtime Install Tool (by Microsoft)
 
-> after that open settings & search Omnisharp , make sure that 
   "Use Omnisharp" checkbox is enabled.

![C# extension omnisharp](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ueajmnpc4vwocv488x3m.png)
![omnisharp auto start](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f89wdnp2n7093re6l1e2.png)

-> check above tools are installed successfully or not by following commands from terminal.
> dotnet --list-sdks
> dotnet  --list-runtimes

![dotnet sdk](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6vdx6qvxx9mm0t2hq1sx.png)

-> Check whether maui workload is exist not.
 > dotnet workload list

![maui workload](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6d0f5v3by8z1h6qxmbtg.png)

-> List all available workloads. 
 > dotnet workload search

![workload list](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mmq59i7d71kn9xcrl9kx.png)

-> Install maui workload
 > dotnet workload install maui

-> Check installed workload
 > dotnet workload list 

![maui workload](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/coomlrq8o6t22j7ew23j.png)


**Step - 2 : Create Maui Project** 

-> Create Maui Template.
> dotnet new maui  

![Maui Template](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3kuypn37d8ojq3bx6d2l.png)

-> open the [project_name].csproj file & perform following acions
> comment this tag <TargetFrameworks>net7.0-android;net7.0-ios;net7.0-maccatalyst</TargetFrameworks> 
 
![target framework](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h4pnvat501oi1ufnu1gy.png)

> dotnet restore (add nuget packages,mentioned in .csproj file)

![restore](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/du67r1ir8eeqb2wr7jef.png)

> dotnet build

![build](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4poqehd67m0grj2s7d5x.png)


**Step - 3 : Let's do some code**

=> Add fonts :

-> Add OpenSans-Regular.ttf & OpenSans-Semibold.ttf  fonts file in the Resources/Fonts folder. (check out my github repo for required resources : [Repo](https://github.com/JayMalli/groot_app-maui-windows_publish/tree/main))  

![font](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y1lckdyherhzvbjk593r.png)


=> AppShell.xaml : 

```
// remove title from header
<ShellContent
    ContentTemplate="{DataTemplate local:MainPage}"
    Route="MainPage"
    Shell.NavBarIsVisible="False" 
/>
```

=> MainPage.xaml

```
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Groot_App_Maui.MainPage">

    <ScrollView>
        <VerticalStackLayout
            Spacing="25"
            Padding="30,0"
            VerticalOptions="Center">

            <Image
                Source="groot_img.jpg" // Add this image in resources folder
                SemanticProperties.Description="Cute groot waving hi to you!"
                HeightRequest="400"
                HorizontalOptions="Center" />

            <Label
                Text="I am Groot!"
                SemanticProperties.HeadingLevel="Level1"
                FontSize="32"
                HorizontalOptions="Center" />
           
              <Button
                FontAttributes="Bold"  
                Text="Click Me"  
                FontSize="{OnPlatform WinUI=16, MacCatalyst=18}"
                HorizontalOptions="Center"
                Clicked="OnClickBtn"  
             /> 

        </VerticalStackLayout>
    </ScrollView>

</ContentPage>

```
-> Please add the Groot image to the Resources/Images folder and the Groot app icon to the Resources/AppIcon folder. You can obtain these files from this [repository](https://github.com/JayMalli/groot_app-maui-windows_publish/tree/main).

![resources](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w7fjpsgs2ipcutvp9vw0.png)

![app icon](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/spkx2k4p2a994cfae8o3.png)


=> MainPage.xaml.cs :

```
// remove unnecessary code

namespace Groot_App_Maui;

public partial class MainPage : ContentPage
{

	public MainPage()
	{
		InitializeComponent();
	}

        public async void OnClickBtn(object sender, EventArgs e)
	{
		await 
 Application.Current.MainPage.DisplayAlert(null, "Again I am Groot :)", "OK");
	} 
}

```

=> [project_name].csproj :

```
// other code
<ItemGroup>
		<!-- App Icon -->
		<MauiIcon Include="Resources\AppIcon\app_icon.png"/>
</ItemGroup>
```
![app icon](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8uazkqpz0zrz3dvqtu35.png)
     
**Step - 4 : Lets run our app**

> dotnet run -f net7.0-windows10.0.19041.0 (from .csproj file)

![Profile error](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9j7rdknx77nnt8ru78in.png)

![Groot happy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/awe0x776u2ewff90jwwi.jpg)

-> yaa yaa! "I know Groot; I forgot to modify the launch settings file of the app."

-> The launchSettings.json is used to configure various settings related to the debugging and launching of your application for different environments and configurations.

=> Modify Properties/launchSettings.json file

```
{
  "profiles": {
    "Windows (Debug)": {
      "commandName": "Project",
      "commandLineArgs": "--device windows --theme Light",
      "workingDirectory": "$(ProjectDir)",
      "launchBrowser": true,
      "launchUrl": "",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "Windows (Release)": {
      "commandName": "Project",
      "commandLineArgs": "--device windows --theme Light",
      "workingDirectory": "$(ProjectDir)",
      "launchBrowser": true,
      "launchUrl": "",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Production"
      }
    },
    "Mac (Debug)": {
      "commandName": "Project",
      "commandLineArgs": "--device macos --theme Light",
      "workingDirectory": "$(ProjectDir)",
      "launchBrowser": true,
      "launchUrl": "",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "Mac (Release)": {
      "commandName": "Project",
      "commandLineArgs": "--device macos --theme Light",
      "workingDirectory": "$(ProjectDir)",
      "launchBrowser": true,
      "launchUrl": "",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Production"
      }
    }
  }
}
```
-> Again run app
> dotnet build 
> dotnet run -f net7.0-windows10.0.19041.0 

-> If the app is not launched or running, then check the Events Log in the Event Viewer,
> Search Menu >> Event Viewer >> Windows Logs >> Application

-> If you encounter this error, add the following code to the .csproj file. 

![Event logs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pmodv0tium0v4b0g87hn.png)

=> .csproj file :  

```
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained><WindowsPackageType>None</WindowsPackageType>
```

![csproj file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e7c97bnvoxsb9dlggw94.png)

-> Again run app
> dotnet build 
> dotnet run -f net7.0-windows10.0.19041.0 

- Yaahh!
![app o/p](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n64hxu6knz9fr55jo906.jpg)

**Step - 5 : Its time to publish our app**

-> We will create an MSIX package to publish the app. For that, we need to create a self-signed certificate to demonstrate our app.
   
-> If you want to learn more about the MSIX package, please visit: [MSIX Docs](https://learn.microsoft.com/en-us/windows/msix/overview) 
 
=> Create Self Signed Certificate : 

-> Open PowerShell as an administrator and execute the following commands:

> New-SelfSignedCertificate -Type Custom `
                          -Subject "CN=<PublisherName>" `
                          -KeyUsage DigitalSignature `
                          -FriendlyName "My temp dev cert" `
                          -CertStoreLocation "Cert:\CurrentUser\My" `
                          -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3", "2.5.29.19={text}") 

// replace PublisherName with name of author e.g. CN=JayMalli

-> You will receive the thumbprint of the certificate upon successful creation. Copy that thumbprint.

![certificate thumbprint](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v6hny79nr3hxx0lexpwe.png)

-> Execute this command in PowerShell to get all thumbprints.  

> Get-ChildItem "Cert:\CurrentUser\My" | Format-Table Subject, FriendlyName, Thumbprint 

---

=> Export Certificate :

-> Open the 'Manage User Certificates' dialogue box using the search menu.

   ![Manage User Certificates](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d3c1ujgy4m6jfz6iqiup.png)

-> Go to Personal>>Certificates>> tab

   ![not trusted certificate](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mpzde5cdiqrues400g2f.png)

-> The self signed certificate is not verified & valid for 1 year.

-> Export the certificate by following these steps.

-> Navigate to the details tab in that certificate dialogue box ,
> Click on Copy to file button >> Next
> do not export private key >> Next
> DERbinary Encoded >> Next
> Specify location & file name by browse option >> Next
> Finish

   ![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1cs7s768ztichoad98zs.png)
 
-> You can find the exported certificate at the specified location in the file system.

---

=> Verify Certificate : 

-> Open manage computer certificates

  ![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c8e4i5mamgof2z9yg7xw.png)

-> Navigate to the 'Trusted Root Certification Authorities.
> Right click on Certificates tab
> All task>> import
> Local machine should be checked >> Next 
> Click on browse button 
> Select certificate from location where you previously stored 
> Place all ecrtifcates in following store should be enable
> Next >> Finish

-> Now, go back to 'Manage User Certificates' and check that the certificate is verified

   ![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e3ew3mwibae3kit1c7qj.png)

=> Sign our app using created certificate :

-> add below code in .csproj file 

// Replace your_certificate_thumbprint with the previously created thumbprint, which was generated in PowerShell.


![csproj file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4punrlxol5zg1n4n7dot.png)


-> update below code in .csproj file

// comment this tags for production mode of app 
// Update the App ID to the appropriate name.


![csproj file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n60axr0ut3xzy9i0d0k4.png)




---

=> Configure resources for production app:

-> Create an 'Assets' folder and place all resources in it. Please check this [repository](https://github.com/JayMalli/groot_app-maui-windows_publish/tree/main) for reference. 

-> Modify Package.appxmanifest file with below code.

// Replace 'Your_Name' with the name you want to display as the publisher in the app.

// Replace 'Your_thumbprint_Name' with the name which was provided in the creation of thumprint. 


![csproj code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/olsgo23gd9cvtqst5uoa.png)

![csproj code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4tfdkj4teiyysicd3vbc.png)

-> Reference this [repo](https://github.com/JayMalli/groot_app-maui-windows_publish/tree/main) for code. 

=> Publish App: 
  
-> execute following command in the terminal

// Replace 'your_certificate_thumbprint' with the previously created thumbprint, which was generated in PowerShell.

> dotnet build  /restore /t:publish /p:TargetFramework=net7.0-windows10.0.19041.0 /p:configuration=release /p:GenerateAppxPackageOnBuild=true /p:AppxPackageSigningEnabled=true /p:PackageCertificateThumbprint=your_certificate_thumbprint

   ![published app msix package](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ldkdtzazkwlflf1ucene.png)

-> Open the MSIX package in the file storage and launch it

   ![installation wizard](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8irxc5riic1y4qsxm8ib.png)

> Install app

   ![app section](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fc2p0wfu38jatztqos2a.png)

> Launch app

=> finally Groot is here! :)  

![production app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q6q1036pkhbpvap7w5ru.png)


=> The example above demonstrates how to develop & publish .NET maui app for windows platform ,  you can find the necessary code in the repository mentioned below.

=> [GithHub Repository](https://github.com/JayMalli/groot_app-maui-windows_publish/tree/main)

Thank you for joining me on this journey of discovery and learning. If you found this blog post valuable and would like to connect further, I'd love to connect with you on LinkedIn. You can find me at [LinkedIn](https://www.linkedin.com/in/jaymalli)

If you have thoughts, questions, or experiences related to this topic, please drop a comment below.