Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cross-platform support #518

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
name: Nightly Build 🌙🛠️

on:
push:
branches: main
paths:
- .github/workflows/nightly.yml
- src/**
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.event_name }}
cancel-in-progress: true

permissions:
contents: write

jobs:
build:
strategy:
matrix:
include:
- os: windows-latest
dotnet-runtime: win-x64
rust-target: x86_64-pc-windows-msvc
- os: windows-latest
dotnet-runtime: win-arm64
rust-target: aarch64-pc-windows-msvc
- os: ubuntu-latest
dotnet-runtime: linux-x64
rust-target: x86_64-unknown-linux-gnu
- os: ubuntu-latest
dotnet-runtime: linux-arm64
rust-target: aarch64-unknown-linux-gnu
- os: macos-latest
dotnet-runtime: osx-arm64
rust-target: aarch64-apple-darwin
bin-suffix: macos-arm64
runs-on: ${{ matrix.os }}
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v4
with:
submodules: true
lfs: true
persist-credentials: false

- uses: moonrepo/setup-rust@v1
with:
channel: stable
targets: ${{ matrix.rust-target }}
cache: false

- if: matrix.rust-target == 'aarch64-unknown-linux-gnu'
run: |
sudo sed -i -e 's/deb mirror/deb [arch=amd64] mirror/g' /etc/apt/sources.list
echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports noble main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list.d/arm64.list
echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports noble-updates main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list.d/arm64.list
echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports noble-backports main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list.d/arm64.list
echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports noble-security main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list.d/arm64.list
sudo dpkg --add-architecture arm64
sudo apt-get update && sudo apt-get install -y gcc-aarch64-linux-gnu

- run: CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER="aarch64-linux-gnu-gcc" cargo build -r --target ${{ matrix.rust-target }}
working-directory: src/WingetCreateCore/Common/Msi/rust-msi

- run: dotnet publish ./WingetCreateCLI.csproj -c Release -r ${{ matrix.dotnet-runtime }} --output ./output
working-directory: src/WingetCreateCLI

- if: matrix.os != 'windows-latest'
run: mv src/WingetCreateCLI/output/WingetCreateCLI ./wingetcreate-${{ matrix.bin-suffix || matrix.dotnet-runtime }}

- if: matrix.os == 'windows-latest'
run: mv src/WingetCreateCLI/output/WingetCreateCLI.exe ./wingetcreate-${{ matrix.dotnet-runtime }}.exe

- name: Delete old release 🗑️
run: |
gh api repos/$GITHUB_REPOSITORY/git/refs/tags/nightly | jq -r '.object.sha' | grep -q $GITHUB_SHA && exit 0
gh release delete nightly -y --cleanup-tag
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- uses: softprops/action-gh-release@v2
with:
name: Nightly release 🌙
tag_name: nightly
draft: false
files: wingetcreate-*
fail_on_unmatched_files: true
token: ${{ secrets.GITHUB_TOKEN }}
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
*.userosscache
*.sln.docstates

# Thumbnails (macOS)
._*

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

Expand Down Expand Up @@ -186,7 +189,7 @@ publish/
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
# *.pubxml
*.publishproj

# Microsoft Azure Web App publish settings. Comment the next line if you want to
Expand Down
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[submodule "src/WingetCreateCore/Common/Msi/rust-msi"]
path = src/WingetCreateCore/Common/Msi/rust-msi\
# TODO: Switch to mdsteele/rust-msi once the PR is merged
# https://github.com/mdsteele/rust-msi/pull/18
url = https://github.com/vedantmgoyal9/rust-msi
shallow = true
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Below is our guidance for how to report issues, propose new features, and submit

## Open Development Workflow

The Windows Package Manager Manifest Creator team is VERY active in this GitHub Repository. In fact, we live in it all day long and carry out all our development in the open!
The Windows Package Manager team is VERY active in this GitHub Repository. In fact, we live in it all day long and carry out all our development in the open!

When the team finds issues we file them in the repository. When we propose new ideas or think-up new features, we file new feature requests. When we work on fixes or features, we create branches and work on those improvements. And when PRs are reviewed, we review in public - including all the good, the bad, and the ugly parts.

Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,22 +72,22 @@ You can also check out this [episode of Open at Microsoft](https://learn.microso

### Using the standalone exe:

The latest version of the standalone exe can be found at https://aka.ms/wingetcreate/latest, and the latest preview version can be found at https://aka.ms/wingetcreate/preview, both of these require [.NET Runtime 6.0](https://dotnet.microsoft.com/en-us/download/dotnet/6.0) to be installed on the build machine. To install this on your build machine in your pipeline, you can include the following dotnet task:
The latest version of the standalone exe can be found at https://aka.ms/wingetcreate/latest, and the latest preview version can be found at https://aka.ms/wingetcreate/preview, both of these require [.NET Runtime 8.0](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) to be installed on the build machine. To install this on your build machine in your pipeline, you can include the following dotnet task:

```yaml
- task: UseDotNet@2
displayName: 'Install .NET Runtime'
inputs:
packageType: sdk
version: '6.x'
version: '8.x'
installationPath: '$(ProgramFiles)\dotnet'
```

Or you can utilize a PowerShell task and run the following script.

```PowerShell
Invoke-WebRequest https://dot.net/v1/dotnet-install.ps1 -OutFile dotnet-install.ps1
.\dotnet-install.ps1 -Runtime dotnet -Architecture x64 -Version 6.0.13 -InstallDir $env:ProgramFiles\dotnet
.\dotnet-install.ps1 -Runtime dotnet -Architecture x64 -Version 8 -InstallDir $env:ProgramFiles\dotnet
```

> [!IMPORTANT]
Expand Down Expand Up @@ -158,11 +158,11 @@ You can install the prerequisites in one of two ways:
* The following workloads:
* .NET Desktop Development
* Universal Windows Platform Development
* Windows 11 SDK (10.0.22000.0) (Tools -> Get Tools and Features -> Individual Components)
* Windows 11 SDK (10.0.26100.0) (Tools -> Get Tools and Features -> Individual Components)

### Building

Open `winget-create\src\WingetCreateCLI.sln` in Visual Studio and build. We currently only build using the solution; command line methods of building a VS solution should work as well.
Open `winget-create\src\WingetCreateCLI.sln` in Visual Studio and build. We currently only build using the solution; command-line methods of building a VS solution should work as well.

## Testing the client

Expand All @@ -181,7 +181,7 @@ Running unit and E2E tests are a great way to ensure that functionality is prese
* Direct link to GitHub [Personal Access Tokens page](https://github.com/settings/tokens).
* `GitHubAppPrivateKey`: Leave blank, this is only used by the build server.

* Set the solution wide runsettings file for the tests
* Set the solution-wide runsettings file for the tests
* Go to `Test` menu > `Configure Run Settings` -> `Select Solution Wide runsettings File` -> Choose your configured runsettings file

> [!CAUTION]
Expand Down
64 changes: 32 additions & 32 deletions src/WingetCreateCLI.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30621.155
# Visual Studio Version 17
VisualStudioVersion = 17.9.34607.119
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WingetCreateCLI", "WingetCreateCLI\WingetCreateCLI.csproj", "{C36B8829-36E2-44BB-942C-00F29FCAE973}"
EndProject
Expand All @@ -24,68 +24,68 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|arm64 = Debug|arm64
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|arm64 = Release|arm64
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C36B8829-36E2-44BB-942C-00F29FCAE973}.Debug|arm64.ActiveCfg = Debug|arm64
{C36B8829-36E2-44BB-942C-00F29FCAE973}.Debug|arm64.Build.0 = Debug|arm64
{C36B8829-36E2-44BB-942C-00F29FCAE973}.Debug|x64.ActiveCfg = Debug|x64
{C36B8829-36E2-44BB-942C-00F29FCAE973}.Debug|x64.Build.0 = Debug|x64
{C36B8829-36E2-44BB-942C-00F29FCAE973}.Debug|x86.ActiveCfg = Debug|x86
{C36B8829-36E2-44BB-942C-00F29FCAE973}.Debug|x86.Build.0 = Debug|x86
{C36B8829-36E2-44BB-942C-00F29FCAE973}.Release|arm64.ActiveCfg = Release|arm64
{C36B8829-36E2-44BB-942C-00F29FCAE973}.Release|arm64.Build.0 = Release|arm64
{C36B8829-36E2-44BB-942C-00F29FCAE973}.Release|x64.ActiveCfg = Release|x64
{C36B8829-36E2-44BB-942C-00F29FCAE973}.Release|x64.Build.0 = Release|x64
{C36B8829-36E2-44BB-942C-00F29FCAE973}.Release|x86.ActiveCfg = Release|x86
{C36B8829-36E2-44BB-942C-00F29FCAE973}.Release|x86.Build.0 = Release|x86
{D61EDBD2-637B-4B5A-848E-2B1A505BE883}.Debug|arm64.ActiveCfg = Debug|arm64
{D61EDBD2-637B-4B5A-848E-2B1A505BE883}.Debug|arm64.Build.0 = Debug|arm64
{D61EDBD2-637B-4B5A-848E-2B1A505BE883}.Debug|x64.ActiveCfg = Debug|x64
{D61EDBD2-637B-4B5A-848E-2B1A505BE883}.Debug|x64.Build.0 = Debug|x64
{D61EDBD2-637B-4B5A-848E-2B1A505BE883}.Debug|x86.ActiveCfg = Debug|x86
{D61EDBD2-637B-4B5A-848E-2B1A505BE883}.Debug|x86.Build.0 = Debug|x86
{D61EDBD2-637B-4B5A-848E-2B1A505BE883}.Release|arm64.ActiveCfg = Release|arm64
{D61EDBD2-637B-4B5A-848E-2B1A505BE883}.Release|arm64.Build.0 = Release|arm64
{D61EDBD2-637B-4B5A-848E-2B1A505BE883}.Release|x64.ActiveCfg = Release|x64
{D61EDBD2-637B-4B5A-848E-2B1A505BE883}.Release|x64.Build.0 = Release|x64
{D61EDBD2-637B-4B5A-848E-2B1A505BE883}.Release|x86.ActiveCfg = Release|x86
{D61EDBD2-637B-4B5A-848E-2B1A505BE883}.Release|x86.Build.0 = Release|x86
{90EB2100-7BDB-4FFC-B657-3A63EEED93F9}.Debug|arm64.ActiveCfg = Debug|arm64
{90EB2100-7BDB-4FFC-B657-3A63EEED93F9}.Debug|arm64.Build.0 = Debug|arm64
{90EB2100-7BDB-4FFC-B657-3A63EEED93F9}.Debug|x64.ActiveCfg = Debug|x64
{90EB2100-7BDB-4FFC-B657-3A63EEED93F9}.Debug|x64.Build.0 = Debug|x64
{90EB2100-7BDB-4FFC-B657-3A63EEED93F9}.Debug|x86.ActiveCfg = Debug|x86
{90EB2100-7BDB-4FFC-B657-3A63EEED93F9}.Debug|x86.Build.0 = Debug|x86
{90EB2100-7BDB-4FFC-B657-3A63EEED93F9}.Release|arm64.ActiveCfg = Release|arm64
{90EB2100-7BDB-4FFC-B657-3A63EEED93F9}.Release|arm64.Build.0 = Release|arm64
{90EB2100-7BDB-4FFC-B657-3A63EEED93F9}.Release|x64.ActiveCfg = Release|x64
{90EB2100-7BDB-4FFC-B657-3A63EEED93F9}.Release|x64.Build.0 = Release|x64
{90EB2100-7BDB-4FFC-B657-3A63EEED93F9}.Release|x86.ActiveCfg = Release|x86
{90EB2100-7BDB-4FFC-B657-3A63EEED93F9}.Release|x86.Build.0 = Release|x86
{5613C196-3D8B-4B5C-9288-B24B01DDA3BE}.Debug|arm64.ActiveCfg = Debug|arm64
{5613C196-3D8B-4B5C-9288-B24B01DDA3BE}.Debug|arm64.Build.0 = Debug|arm64
{5613C196-3D8B-4B5C-9288-B24B01DDA3BE}.Debug|x64.ActiveCfg = Debug|x64
{5613C196-3D8B-4B5C-9288-B24B01DDA3BE}.Debug|x64.Build.0 = Debug|x64
{5613C196-3D8B-4B5C-9288-B24B01DDA3BE}.Debug|x86.ActiveCfg = Debug|x86
{5613C196-3D8B-4B5C-9288-B24B01DDA3BE}.Debug|x86.Build.0 = Debug|x86
{5613C196-3D8B-4B5C-9288-B24B01DDA3BE}.Release|arm64.ActiveCfg = Release|arm64
{5613C196-3D8B-4B5C-9288-B24B01DDA3BE}.Release|arm64.Build.0 = Release|arm64
{5613C196-3D8B-4B5C-9288-B24B01DDA3BE}.Release|x64.ActiveCfg = Release|x64
{5613C196-3D8B-4B5C-9288-B24B01DDA3BE}.Release|x64.Build.0 = Release|x64
{5613C196-3D8B-4B5C-9288-B24B01DDA3BE}.Release|x86.ActiveCfg = Release|x86
{5613C196-3D8B-4B5C-9288-B24B01DDA3BE}.Release|x86.Build.0 = Release|x86
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Debug|arm64.ActiveCfg = Debug|arm64
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Debug|arm64.Build.0 = Debug|arm64
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Debug|arm64.Deploy.0 = Debug|arm64
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Debug|x64.ActiveCfg = Debug|x64
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Debug|x64.Build.0 = Debug|x64
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Debug|x64.Deploy.0 = Debug|x64
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Debug|x86.ActiveCfg = Debug|x86
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Debug|x86.Build.0 = Debug|x86
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Debug|x86.Deploy.0 = Debug|x86
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Release|arm64.ActiveCfg = Release|arm64
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Release|arm64.Build.0 = Release|arm64
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Release|arm64.Deploy.0 = Release|arm64
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Release|x64.ActiveCfg = Release|x64
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Release|x64.Build.0 = Release|x64
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Release|x64.Deploy.0 = Release|x64
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Release|x86.ActiveCfg = Release|x86
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Release|x86.Build.0 = Release|x86
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Release|x86.Deploy.0 = Release|x86
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Debug|arm64.ActiveCfg = Debug|arm64
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Debug|arm64.Build.0 = Debug|arm64
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Debug|arm64.Deploy.0 = Debug|arm64
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Debug|x64.ActiveCfg = Debug|x64
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Debug|x64.Build.0 = Debug|x64
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Debug|x64.Deploy.0 = Debug|x64
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Debug|x86.ActiveCfg = Debug|x86
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Debug|x86.Build.0 = Debug|x86
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Debug|x86.Deploy.0 = Debug|x86
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Release|arm64.ActiveCfg = Release|arm64
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Release|arm64.Build.0 = Release|arm64
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Release|arm64.Deploy.0 = Release|arm64
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Release|x64.ActiveCfg = Release|x64
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Release|x64.Build.0 = Release|x64
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Release|x64.Deploy.0 = Release|x64
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Release|x86.ActiveCfg = Release|x86
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Release|x86.Build.0 = Release|x86
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Release|x86.Deploy.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
15 changes: 10 additions & 5 deletions src/WingetCreateCLI/Commands/BaseCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public abstract class BaseCommand
/// <summary>
/// Program name of the app.
/// </summary>
protected const string ProgramApplicationAlias = "wingetcreate.exe";
protected const string ProgramApplicationAlias = "wingetcreate";

/// <summary>
/// Dictionary to store paths to downloaded installers from a given URL.
Expand Down Expand Up @@ -388,15 +388,20 @@ protected static async Task<string> DownloadPackageFile(string installerUrl)
/// <returns>Bool indicating the validity of the manifest file. </returns>
protected static bool ValidateManifest(string manifestPath)
{
(bool success, string message) = WinGetUtil.ValidateManifest(manifestPath);
(bool result, string message) = WinGetUtil.ValidateManifest(manifestPath);

if (success)
if (result)
{
Logger.InfoLocalized(nameof(Resources.ManifestValidationSucceeded_Message), success);
Logger.InfoLocalized(nameof(Resources.ManifestValidationSucceeded_Message), result);
}
else if (message == Constants.ManifestValidationUnavailable)
{
Logger.ErrorLocalized(nameof(Resources.ManifestValidationSucceeded_Message), message);
Logger.WarnLocalized(nameof(Resources.ManifestValidationUnavailableOnUnix_Message));
}
else
{
Logger.ErrorLocalized(nameof(Resources.ManifestValidationSucceeded_Message), success);
Logger.ErrorLocalized(nameof(Resources.ManifestValidationSucceeded_Message), result);
Logger.Error(message);
return false;
}
Expand Down
29 changes: 23 additions & 6 deletions src/WingetCreateCLI/Commands/SettingsCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace Microsoft.WingetCreateCLI.Commands
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using CommandLine;
using Microsoft.WingetCreateCLI.Logging;
Expand Down Expand Up @@ -50,7 +51,7 @@ public override Task<bool> Execute()
}
else
{
this.DisplayParsingErrors(settingsFileErrors, UserSettings.SettingsJsonPath);
DisplayParsingErrors(settingsFileErrors, UserSettings.SettingsJsonPath);
}
}

Expand All @@ -60,19 +61,19 @@ public override Task<bool> Execute()

if (!isBackupValid)
{
this.DisplayParsingErrors(backupFileErrors, UserSettings.SettingsBackupJsonPath);
DisplayParsingErrors(backupFileErrors, UserSettings.SettingsBackupJsonPath);
}
}

return Task.FromResult(commandEvent.IsSuccessful = this.OpenJsonFile(UserSettings.SettingsJsonPath));
return Task.FromResult(commandEvent.IsSuccessful = OpenJsonFile(UserSettings.SettingsJsonPath));
}
finally
{
TelemetryManager.Log.WriteEvent(commandEvent);
}
}

private void DisplayParsingErrors(List<string> errors, string path)
private static void DisplayParsingErrors(List<string> errors, string path)
{
Logger.WarnLocalized(nameof(Resources.ErrorParsingSettingsFile_Message), Path.GetFileName(path));

Expand All @@ -83,7 +84,7 @@ private void DisplayParsingErrors(List<string> errors, string path)
}
}

private bool OpenJsonFile(string path)
private static bool OpenJsonFile(string path)
{
if (!File.Exists(path))
{
Expand All @@ -92,7 +93,23 @@ private bool OpenJsonFile(string path)

try
{
Process.Start(new ProcessStartInfo { UseShellExecute = true, FileName = path });
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
Process.Start(new ProcessStartInfo { UseShellExecute = true, FileName = path });
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
Process.Start("xdg-open", path);
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
Process.Start("open", path);
}
else
{
throw new PlatformNotSupportedException();
}

return true;
}
catch (Win32Exception e)
Expand Down
Loading