Add Visual Studio extension for Linux platform support

VSIX extension that adds:
- "OpenMaui Linux App" project template in File → New → Project
- Pre-configured launch profiles for Linux debugging
- WSL integration for Windows developers
- x64 and ARM64 build configurations

Launch Profiles included:
- Linux (Local) - Direct execution
- Linux (WSL) - Run via WSL
- Linux (x64 Release) - Release build for x64
- Linux (ARM64 Release) - Release build for ARM64
- Publish Linux x64/ARM64 - Self-contained publishing

Build with: msbuild /p:Configuration=Release
Output: OpenMaui.VisualStudio.vsix
This commit is contained in:
logikonline
2025-12-19 05:13:16 -05:00
parent d238dde5a4
commit ae5c9ab738
13 changed files with 549 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
MIT License
Copyright (c) 2025 MarketAlly LLC
Lead Architect: David H. Friedel Jr.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,44 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<!-- VSIX Properties -->
<GeneratePkgDefFile>true</GeneratePkgDefFile>
<IncludeAssemblyInVSIXContainer>true</IncludeAssemblyInVSIXContainer>
<IncludeDebugSymbolsInVSIXContainer>false</IncludeDebugSymbolsInVSIXContainer>
<IncludeDebugSymbolsInLocalVSIXDeployment>false</IncludeDebugSymbolsInLocalVSIXDeployment>
<CopyBuildOutputToOutputDirectory>true</CopyBuildOutputToOutputDirectory>
<CopyOutputSymbolsToOutputDirectory>false</CopyOutputSymbolsToOutputDirectory>
<UseCodebase>true</UseCodebase>
<!-- Extension Info -->
<ExtensionInstallationRoot>Extensions</ExtensionInstallationRoot>
<ExtensionInstallationFolder>MarketAlly\OpenMaui</ExtensionInstallationFolder>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.VSSDK.BuildTools" Version="17.8.2365" />
<PackageReference Include="Microsoft.VisualStudio.SDK" Version="17.8.37221" />
</ItemGroup>
<ItemGroup>
<None Include="source.extension.vsixmanifest">
<SubType>Designer</SubType>
</None>
</ItemGroup>
<ItemGroup>
<Content Include="ProjectTemplates\**\*">
<IncludeInVSIX>true</IncludeInVSIX>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Resources\**\*">
<IncludeInVSIX>true</IncludeInVSIX>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,17 @@
namespace $safeprojectname$;
/// <summary>
/// Application configuration and lifecycle management.
/// </summary>
public partial class App
{
public App()
{
InitializeComponent();
}
private void InitializeComponent()
{
// Initialize application resources here
}
}

View File

@@ -0,0 +1,76 @@
using Microsoft.Maui.Controls;
namespace $safeprojectname$;
/// <summary>
/// The main page of the application.
/// </summary>
public partial class MainPage : ContentPage
{
private int _count = 0;
public MainPage()
{
InitializeComponent();
}
private void InitializeComponent()
{
Title = "Home";
var layout = new VerticalStackLayout
{
Spacing = 25,
Padding = new Thickness(30, 0),
VerticalOptions = LayoutOptions.Center
};
var welcomeLabel = new Label
{
Text = "Hello, OpenMaui!",
FontSize = 32,
HorizontalOptions = LayoutOptions.Center
};
var instructionLabel = new Label
{
Text = "Welcome to .NET MAUI on Linux",
FontSize = 18,
HorizontalOptions = LayoutOptions.Center
};
var counterButton = new Button
{
Text = "Click me",
HorizontalOptions = LayoutOptions.Center
};
counterButton.Clicked += OnCounterClicked;
var image = new Image
{
Source = "dotnet_bot.png",
HeightRequest = 185,
HorizontalOptions = LayoutOptions.Center
};
layout.Children.Add(welcomeLabel);
layout.Children.Add(instructionLabel);
layout.Children.Add(counterButton);
layout.Children.Add(image);
Content = new ScrollView { Content = layout };
}
private void OnCounterClicked(object? sender, EventArgs e)
{
_count++;
if (sender is Button button)
{
button.Text = _count == 1
? $"Clicked {_count} time"
: $"Clicked {_count} times";
}
}
}

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8" ?>
<!--
Note: OpenMaui currently uses code-based UI (MainPage.cs).
This XAML file is provided for future XAML support compatibility.
The code-behind in MainPage.cs takes precedence.
-->
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="$safeprojectname$.MainPage">
<ScrollView>
<VerticalStackLayout
Padding="30,0"
Spacing="25">
<Label
Text="Hello, OpenMaui!"
Style="{StaticResource Headline}"
SemanticProperties.HeadingLevel="Level1" />
<Label
Text="Welcome to .NET MAUI on Linux"
Style="{StaticResource SubHeadline}"
SemanticProperties.Description="Welcome message" />
<Button
x:Name="CounterBtn"
Text="Click me"
Clicked="OnCounterClicked"
HorizontalOptions="Fill" />
<Image
Source="dotnet_bot.png"
HeightRequest="185"
Aspect="AspectFit"
SemanticProperties.Description="dot net bot waving" />
</VerticalStackLayout>
</ScrollView>
</ContentPage>

View File

@@ -0,0 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>$safeprojectname$</RootNamespace>
<AssemblyName>$safeprojectname$</AssemblyName>
<ApplicationTitle>$projectname$</ApplicationTitle>
<!-- Linux Runtime -->
<RuntimeIdentifiers>linux-x64;linux-arm64</RuntimeIdentifiers>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<DefineConstants>$(DefineConstants);DEBUG</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<PublishSingleFile>true</PublishSingleFile>
<SelfContained>true</SelfContained>
<PublishTrimmed>false</PublishTrimmed>
</PropertyGroup>
<ItemGroup>
<!-- OpenMaui Linux Platform -->
<PackageReference Include="OpenMaui.Controls.Linux" Version="1.0.0-preview.*" />
<!-- Core MAUI packages -->
<PackageReference Include="Microsoft.Maui.Controls" Version="9.0.*" />
<PackageReference Include="Microsoft.Maui.Graphics" Version="9.0.*" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\**\*" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,43 @@
<VSTemplate Version="3.0.0" Type="Project" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005">
<TemplateData>
<Name>OpenMaui Linux App</Name>
<Description>A .NET MAUI application targeting Linux desktop using OpenMaui and SkiaSharp rendering.</Description>
<Icon>__TemplateIcon.ico</Icon>
<PreviewImage>__PreviewImage.png</PreviewImage>
<ProjectType>CSharp</ProjectType>
<ProjectSubType></ProjectSubType>
<LanguageTag>csharp</LanguageTag>
<PlatformTag>linux</PlatformTag>
<ProjectTypeTag>desktop</ProjectTypeTag>
<ProjectTypeTag>maui</ProjectTypeTag>
<RequiredFrameworkVersion>4.8</RequiredFrameworkVersion>
<SortOrder>1000</SortOrder>
<TemplateID>OpenMaui.Linux.App.CSharp</TemplateID>
<CreateNewFolder>true</CreateNewFolder>
<DefaultName>OpenMauiLinuxApp</DefaultName>
<ProvideDefaultName>true</ProvideDefaultName>
<LocationField>Enabled</LocationField>
<EnableLocationBrowseButton>true</EnableLocationBrowseButton>
<CreateInPlace>true</CreateInPlace>
</TemplateData>
<TemplateContent>
<Project File="OpenMauiLinuxApp.csproj" ReplaceParameters="true">
<ProjectItem ReplaceParameters="true" TargetFileName="Program.cs">Program.cs</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="App.cs">App.cs</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="MainPage.cs">MainPage.cs</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="MainPage.xaml">MainPage.xaml</ProjectItem>
<Folder Name="Properties" TargetFolderName="Properties">
<ProjectItem ReplaceParameters="true" TargetFileName="launchSettings.json">launchSettings.json</ProjectItem>
</Folder>
<Folder Name="Resources" TargetFolderName="Resources">
<Folder Name="Images" TargetFolderName="Images">
<ProjectItem TargetFileName="dotnet_bot.png">dotnet_bot.png</ProjectItem>
</Folder>
</Folder>
</Project>
</TemplateContent>
<WizardExtension>
<Assembly>Microsoft.VisualStudio.TemplateEngine.Wizard, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</Assembly>
<FullClassName>Microsoft.VisualStudio.TemplateEngine.Wizard.TemplateEngineWizard</FullClassName>
</WizardExtension>
</VSTemplate>

View File

@@ -0,0 +1,20 @@
using OpenMaui.Platform.Linux;
namespace $safeprojectname$;
public class Program
{
public static void Main(string[] args)
{
var app = new LinuxApplication();
// Configure the application
app.Title = "$projectname$";
// Set the main page
app.MainPage = new MainPage();
// Run the application
app.Run();
}
}

View File

@@ -0,0 +1,49 @@
{
"profiles": {
"Linux (Local)": {
"commandName": "Project",
"commandLineArgs": "",
"environmentVariables": {
"DISPLAY": ":0",
"DOTNET_ENVIRONMENT": "Development"
}
},
"Linux (WSL)": {
"commandName": "Executable",
"executablePath": "wsl.exe",
"commandLineArgs": "-e dotnet run --project .",
"workingDirectory": "${workspaceFolder}",
"environmentVariables": {
"DISPLAY": ":0",
"WAYLAND_DISPLAY": "",
"DOTNET_ENVIRONMENT": "Development"
}
},
"Linux (x64 Release)": {
"commandName": "Executable",
"executablePath": "dotnet",
"commandLineArgs": "run -c Release -r linux-x64",
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Production"
}
},
"Linux (ARM64 Release)": {
"commandName": "Executable",
"executablePath": "dotnet",
"commandLineArgs": "run -c Release -r linux-arm64",
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Production"
}
},
"Publish Linux x64": {
"commandName": "Executable",
"executablePath": "dotnet",
"commandLineArgs": "publish -c Release -r linux-x64 --self-contained -o ./publish/linux-x64"
},
"Publish Linux ARM64": {
"commandName": "Executable",
"executablePath": "dotnet",
"commandLineArgs": "publish -c Release -r linux-arm64 --self-contained -o ./publish/linux-arm64"
}
}
}

View File

@@ -0,0 +1,3 @@
# Placeholder for dotnet_bot.png
# Download from: https://raw.githubusercontent.com/dotnet/brand/main/dotnet-bot/dotnet-bot_waving.png
# Rename to: dotnet_bot.png

View File

@@ -0,0 +1,3 @@
# Add the following images:
# - Icon.png (128x128) - Extension icon
# - Preview.png (200x200) - Preview image for marketplace

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011">
<Metadata>
<Identity Id="OpenMaui.VisualStudio.a1b2c3d4-e5f6-7890-abcd-ef1234567890" Version="1.0.0" Language="en-US" Publisher="MarketAlly LLC" />
<DisplayName>OpenMaui - Linux Platform for .NET MAUI</DisplayName>
<Description xml:space="preserve">Adds Linux platform support to .NET MAUI projects in Visual Studio. Build and deploy MAUI applications to Linux desktops with full SkiaSharp rendering support.
Features:
• Linux project templates
• Linux build configurations
• WSL debugging integration
• Remote Linux debugging
• Linux-specific launch profiles
Developed by MarketAlly LLC
Lead Architect: David H. Friedel Jr.</Description>
<MoreInfo>https://github.com/open-maui/maui-linux</MoreInfo>
<License>LICENSE.txt</License>
<GettingStartedGuide>https://github.com/open-maui/maui-linux/blob/main/docs/GETTING_STARTED.md</GettingStartedGuide>
<ReleaseNotes>https://github.com/open-maui/maui-linux/releases</ReleaseNotes>
<Icon>Resources\Icon.png</Icon>
<PreviewImage>Resources\Preview.png</PreviewImage>
<Tags>maui, linux, desktop, cross-platform, skia, openmaui, dotnet</Tags>
</Metadata>
<Installation>
<InstallationTarget Id="Microsoft.VisualStudio.Community" Version="[17.0,18.0)">
<ProductArchitecture>amd64</ProductArchitecture>
</InstallationTarget>
<InstallationTarget Id="Microsoft.VisualStudio.Pro" Version="[17.0,18.0)">
<ProductArchitecture>amd64</ProductArchitecture>
</InstallationTarget>
<InstallationTarget Id="Microsoft.VisualStudio.Enterprise" Version="[17.0,18.0)">
<ProductArchitecture>amd64</ProductArchitecture>
</InstallationTarget>
</Installation>
<Dependencies>
<Dependency Id="Microsoft.Framework.NDP" DisplayName="Microsoft .NET Framework" d:Source="Manual" Version="[4.8,)" />
<Dependency Id="Microsoft.VisualStudio.Component.CoreEditor" DisplayName="Visual Studio core editor" d:Source="Installed" Version="[17.0,18.0)" />
<Dependency Id="Microsoft.VisualStudio.Workload.NetCrossPlat" DisplayName=".NET MAUI Workload" d:Source="Installed" Version="[17.0,18.0)" />
</Dependencies>
<Prerequisites>
<Prerequisite Id="Microsoft.VisualStudio.Component.CoreEditor" Version="[17.0,18.0)" DisplayName="Visual Studio core editor" />
</Prerequisites>
<Assets>
<Asset Type="Microsoft.VisualStudio.ProjectTemplate" d:Source="File" Path="ProjectTemplates" d:TargetPath="ProjectTemplates" />
<Asset Type="Microsoft.VisualStudio.VsPackage" d:Source="Project" d:ProjectName="%CurrentProject%" Path="|%CurrentProject%;PkgdefProjectOutputGroup|" />
</Assets>
</PackageManifest>