Skip to content

Commit d5bc8c9

Browse files
committed
Cross-platform support
1 parent 7826f51 commit d5bc8c9

30 files changed

+1170
-658
lines changed

.github/workflows/nightly.yml

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
name: Nightly Build 🌙🛠️
2+
3+
on:
4+
push:
5+
branches: main
6+
paths:
7+
- .github/workflows/nightly.yml
8+
- src/**
9+
workflow_dispatch:
10+
11+
concurrency:
12+
group: ${{ github.workflow }}-${{ github.event_name }}
13+
cancel-in-progress: true
14+
15+
permissions:
16+
contents: write
17+
18+
jobs:
19+
build:
20+
strategy:
21+
matrix:
22+
include:
23+
- os: windows-latest
24+
dotnet-runtime: win-x64
25+
rust-target: x86_64-pc-windows-msvc
26+
- os: windows-latest
27+
dotnet-runtime: win-arm64
28+
rust-target: aarch64-pc-windows-msvc
29+
- os: ubuntu-latest
30+
dotnet-runtime: linux-x64
31+
rust-target: x86_64-unknown-linux-gnu
32+
- os: ubuntu-latest
33+
dotnet-runtime: linux-arm64
34+
rust-target: aarch64-unknown-linux-gnu
35+
- os: macos-latest
36+
dotnet-runtime: osx-arm64
37+
rust-target: aarch64-apple-darwin
38+
bin-suffix: macos-arm64
39+
runs-on: ${{ matrix.os }}
40+
defaults:
41+
run:
42+
shell: bash
43+
steps:
44+
- uses: actions/checkout@v4
45+
with:
46+
submodules: true
47+
lfs: true
48+
persist-credentials: false
49+
50+
- uses: moonrepo/setup-rust@v1
51+
with:
52+
channel: stable
53+
targets: ${{ matrix.rust-target }}
54+
cache: false
55+
56+
- if: matrix.rust-target == 'aarch64-unknown-linux-gnu'
57+
run: |
58+
sudo sed -i -e 's/deb mirror/deb [arch=amd64] mirror/g' /etc/apt/sources.list
59+
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
60+
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
61+
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
62+
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
63+
sudo dpkg --add-architecture arm64
64+
sudo apt-get update && sudo apt-get install -y gcc-aarch64-linux-gnu
65+
66+
- run: CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER="aarch64-linux-gnu-gcc" cargo build -r --target ${{ matrix.rust-target }}
67+
working-directory: src/WingetCreateCore/Common/Msi/rust-msi
68+
69+
- run: dotnet publish ./WingetCreateCLI.csproj -c Release -r ${{ matrix.dotnet-runtime }} --output ./output
70+
working-directory: src/WingetCreateCLI
71+
72+
- if: matrix.os != 'windows-latest'
73+
run: mv src/WingetCreateCLI/output/WingetCreateCLI ./wingetcreate-${{ matrix.bin-suffix || matrix.dotnet-runtime }}
74+
75+
- if: matrix.os == 'windows-latest'
76+
run: mv src/WingetCreateCLI/output/WingetCreateCLI.exe ./wingetcreate-${{ matrix.dotnet-runtime }}.exe
77+
78+
- name: Delete old release 🗑️
79+
run: |
80+
gh api repos/$GITHUB_REPOSITORY/git/refs/tags/nightly | jq -r '.object.sha' | grep -q $GITHUB_SHA && exit 0
81+
gh release delete nightly -y --cleanup-tag
82+
env:
83+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
84+
85+
- uses: softprops/action-gh-release@v2
86+
with:
87+
name: Nightly release 🌙
88+
tag_name: nightly
89+
draft: false
90+
files: wingetcreate-*
91+
fail_on_unmatched_files: true
92+
token: ${{ secrets.GITHUB_TOKEN }}

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
*.userosscache
1111
*.sln.docstates
1212

13+
# Thumbnails (macOS)
14+
._*
15+
1316
# User-specific files (MonoDevelop/Xamarin Studio)
1417
*.userprefs
1518

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

192195
# Microsoft Azure Web App publish settings. Comment the next line if you want to

.gitmodules

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[submodule "src/WingetCreateCore/Common/Msi/rust-msi"]
2+
path = src/WingetCreateCore/Common/Msi/rust-msi\
3+
# TODO: Switch to mdsteele/rust-msi once the PR is merged
4+
# https://github.com/mdsteele/rust-msi/pull/18
5+
url = https://github.com/vedantmgoyal9/rust-msi
6+
shallow = true

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Below is our guidance for how to report issues, propose new features, and submit
44

55
## Open Development Workflow
66

7-
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!
7+
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!
88

99
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.
1010

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,22 +72,22 @@ You can also check out this [episode of Open at Microsoft](https://learn.microso
7272

7373
### Using the standalone exe:
7474

75-
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:
75+
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:
7676

7777
```yaml
7878
- task: UseDotNet@2
7979
displayName: 'Install .NET Runtime'
8080
inputs:
8181
packageType: sdk
82-
version: '6.x'
82+
version: '8.x'
8383
installationPath: '$(ProgramFiles)\dotnet'
8484
```
8585
8686
Or you can utilize a PowerShell task and run the following script.
8787
8888
```PowerShell
8989
Invoke-WebRequest https://dot.net/v1/dotnet-install.ps1 -OutFile dotnet-install.ps1
90-
.\dotnet-install.ps1 -Runtime dotnet -Architecture x64 -Version 6.0.13 -InstallDir $env:ProgramFiles\dotnet
90+
.\dotnet-install.ps1 -Runtime dotnet -Architecture x64 -Version 8 -InstallDir $env:ProgramFiles\dotnet
9191
```
9292

9393
> [!IMPORTANT]
@@ -158,11 +158,11 @@ You can install the prerequisites in one of two ways:
158158
* The following workloads:
159159
* .NET Desktop Development
160160
* Universal Windows Platform Development
161-
* Windows 11 SDK (10.0.22000.0) (Tools -> Get Tools and Features -> Individual Components)
161+
* Windows 11 SDK (10.0.22621.0) (Tools -> Get Tools and Features -> Individual Components)
162162

163163
### Building
164164

165-
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.
165+
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.
166166

167167
## Testing the client
168168

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

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

187187
> [!CAUTION]

src/WingetCreateCLI.sln

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
3-
# Visual Studio Version 16
4-
VisualStudioVersion = 16.0.30621.155
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.9.34607.119
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WingetCreateCLI", "WingetCreateCLI\WingetCreateCLI.csproj", "{C36B8829-36E2-44BB-942C-00F29FCAE973}"
77
EndProject
@@ -24,68 +24,68 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
2424
EndProject
2525
Global
2626
GlobalSection(SolutionConfigurationPlatforms) = preSolution
27+
Debug|arm64 = Debug|arm64
2728
Debug|x64 = Debug|x64
28-
Debug|x86 = Debug|x86
29+
Release|arm64 = Release|arm64
2930
Release|x64 = Release|x64
30-
Release|x86 = Release|x86
3131
EndGlobalSection
3232
GlobalSection(ProjectConfigurationPlatforms) = postSolution
33+
{C36B8829-36E2-44BB-942C-00F29FCAE973}.Debug|arm64.ActiveCfg = Debug|arm64
34+
{C36B8829-36E2-44BB-942C-00F29FCAE973}.Debug|arm64.Build.0 = Debug|arm64
3335
{C36B8829-36E2-44BB-942C-00F29FCAE973}.Debug|x64.ActiveCfg = Debug|x64
3436
{C36B8829-36E2-44BB-942C-00F29FCAE973}.Debug|x64.Build.0 = Debug|x64
35-
{C36B8829-36E2-44BB-942C-00F29FCAE973}.Debug|x86.ActiveCfg = Debug|x86
36-
{C36B8829-36E2-44BB-942C-00F29FCAE973}.Debug|x86.Build.0 = Debug|x86
37+
{C36B8829-36E2-44BB-942C-00F29FCAE973}.Release|arm64.ActiveCfg = Release|arm64
38+
{C36B8829-36E2-44BB-942C-00F29FCAE973}.Release|arm64.Build.0 = Release|arm64
3739
{C36B8829-36E2-44BB-942C-00F29FCAE973}.Release|x64.ActiveCfg = Release|x64
3840
{C36B8829-36E2-44BB-942C-00F29FCAE973}.Release|x64.Build.0 = Release|x64
39-
{C36B8829-36E2-44BB-942C-00F29FCAE973}.Release|x86.ActiveCfg = Release|x86
40-
{C36B8829-36E2-44BB-942C-00F29FCAE973}.Release|x86.Build.0 = Release|x86
41+
{D61EDBD2-637B-4B5A-848E-2B1A505BE883}.Debug|arm64.ActiveCfg = Debug|arm64
42+
{D61EDBD2-637B-4B5A-848E-2B1A505BE883}.Debug|arm64.Build.0 = Debug|arm64
4143
{D61EDBD2-637B-4B5A-848E-2B1A505BE883}.Debug|x64.ActiveCfg = Debug|x64
4244
{D61EDBD2-637B-4B5A-848E-2B1A505BE883}.Debug|x64.Build.0 = Debug|x64
43-
{D61EDBD2-637B-4B5A-848E-2B1A505BE883}.Debug|x86.ActiveCfg = Debug|x86
44-
{D61EDBD2-637B-4B5A-848E-2B1A505BE883}.Debug|x86.Build.0 = Debug|x86
45+
{D61EDBD2-637B-4B5A-848E-2B1A505BE883}.Release|arm64.ActiveCfg = Release|arm64
46+
{D61EDBD2-637B-4B5A-848E-2B1A505BE883}.Release|arm64.Build.0 = Release|arm64
4547
{D61EDBD2-637B-4B5A-848E-2B1A505BE883}.Release|x64.ActiveCfg = Release|x64
4648
{D61EDBD2-637B-4B5A-848E-2B1A505BE883}.Release|x64.Build.0 = Release|x64
47-
{D61EDBD2-637B-4B5A-848E-2B1A505BE883}.Release|x86.ActiveCfg = Release|x86
48-
{D61EDBD2-637B-4B5A-848E-2B1A505BE883}.Release|x86.Build.0 = Release|x86
49+
{90EB2100-7BDB-4FFC-B657-3A63EEED93F9}.Debug|arm64.ActiveCfg = Debug|arm64
50+
{90EB2100-7BDB-4FFC-B657-3A63EEED93F9}.Debug|arm64.Build.0 = Debug|arm64
4951
{90EB2100-7BDB-4FFC-B657-3A63EEED93F9}.Debug|x64.ActiveCfg = Debug|x64
5052
{90EB2100-7BDB-4FFC-B657-3A63EEED93F9}.Debug|x64.Build.0 = Debug|x64
51-
{90EB2100-7BDB-4FFC-B657-3A63EEED93F9}.Debug|x86.ActiveCfg = Debug|x86
52-
{90EB2100-7BDB-4FFC-B657-3A63EEED93F9}.Debug|x86.Build.0 = Debug|x86
53+
{90EB2100-7BDB-4FFC-B657-3A63EEED93F9}.Release|arm64.ActiveCfg = Release|arm64
54+
{90EB2100-7BDB-4FFC-B657-3A63EEED93F9}.Release|arm64.Build.0 = Release|arm64
5355
{90EB2100-7BDB-4FFC-B657-3A63EEED93F9}.Release|x64.ActiveCfg = Release|x64
5456
{90EB2100-7BDB-4FFC-B657-3A63EEED93F9}.Release|x64.Build.0 = Release|x64
55-
{90EB2100-7BDB-4FFC-B657-3A63EEED93F9}.Release|x86.ActiveCfg = Release|x86
56-
{90EB2100-7BDB-4FFC-B657-3A63EEED93F9}.Release|x86.Build.0 = Release|x86
57+
{5613C196-3D8B-4B5C-9288-B24B01DDA3BE}.Debug|arm64.ActiveCfg = Debug|arm64
58+
{5613C196-3D8B-4B5C-9288-B24B01DDA3BE}.Debug|arm64.Build.0 = Debug|arm64
5759
{5613C196-3D8B-4B5C-9288-B24B01DDA3BE}.Debug|x64.ActiveCfg = Debug|x64
5860
{5613C196-3D8B-4B5C-9288-B24B01DDA3BE}.Debug|x64.Build.0 = Debug|x64
59-
{5613C196-3D8B-4B5C-9288-B24B01DDA3BE}.Debug|x86.ActiveCfg = Debug|x86
60-
{5613C196-3D8B-4B5C-9288-B24B01DDA3BE}.Debug|x86.Build.0 = Debug|x86
61+
{5613C196-3D8B-4B5C-9288-B24B01DDA3BE}.Release|arm64.ActiveCfg = Release|arm64
62+
{5613C196-3D8B-4B5C-9288-B24B01DDA3BE}.Release|arm64.Build.0 = Release|arm64
6163
{5613C196-3D8B-4B5C-9288-B24B01DDA3BE}.Release|x64.ActiveCfg = Release|x64
6264
{5613C196-3D8B-4B5C-9288-B24B01DDA3BE}.Release|x64.Build.0 = Release|x64
63-
{5613C196-3D8B-4B5C-9288-B24B01DDA3BE}.Release|x86.ActiveCfg = Release|x86
64-
{5613C196-3D8B-4B5C-9288-B24B01DDA3BE}.Release|x86.Build.0 = Release|x86
65+
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Debug|arm64.ActiveCfg = Debug|arm64
66+
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Debug|arm64.Build.0 = Debug|arm64
67+
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Debug|arm64.Deploy.0 = Debug|arm64
6568
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Debug|x64.ActiveCfg = Debug|x64
6669
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Debug|x64.Build.0 = Debug|x64
6770
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Debug|x64.Deploy.0 = Debug|x64
68-
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Debug|x86.ActiveCfg = Debug|x86
69-
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Debug|x86.Build.0 = Debug|x86
70-
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Debug|x86.Deploy.0 = Debug|x86
71+
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Release|arm64.ActiveCfg = Release|arm64
72+
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Release|arm64.Build.0 = Release|arm64
73+
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Release|arm64.Deploy.0 = Release|arm64
7174
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Release|x64.ActiveCfg = Release|x64
7275
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Release|x64.Build.0 = Release|x64
7376
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Release|x64.Deploy.0 = Release|x64
74-
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Release|x86.ActiveCfg = Release|x86
75-
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Release|x86.Build.0 = Release|x86
76-
{154EB646-D902-41B5-9CE1-E78ACC63AA0A}.Release|x86.Deploy.0 = Release|x86
77+
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Debug|arm64.ActiveCfg = Debug|arm64
78+
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Debug|arm64.Build.0 = Debug|arm64
79+
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Debug|arm64.Deploy.0 = Debug|arm64
7780
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Debug|x64.ActiveCfg = Debug|x64
7881
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Debug|x64.Build.0 = Debug|x64
7982
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Debug|x64.Deploy.0 = Debug|x64
80-
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Debug|x86.ActiveCfg = Debug|x86
81-
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Debug|x86.Build.0 = Debug|x86
82-
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Debug|x86.Deploy.0 = Debug|x86
83+
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Release|arm64.ActiveCfg = Release|arm64
84+
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Release|arm64.Build.0 = Release|arm64
85+
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Release|arm64.Deploy.0 = Release|arm64
8386
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Release|x64.ActiveCfg = Release|x64
8487
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Release|x64.Build.0 = Release|x64
8588
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Release|x64.Deploy.0 = Release|x64
86-
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Release|x86.ActiveCfg = Release|x86
87-
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Release|x86.Build.0 = Release|x86
88-
{AC37DFD2-1332-4282-B373-8DCF8BB4E3BA}.Release|x86.Deploy.0 = Release|x86
8989
EndGlobalSection
9090
GlobalSection(SolutionProperties) = preSolution
9191
HideSolutionNode = FALSE

src/WingetCreateCLI/Commands/BaseCommand.cs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public abstract class BaseCommand
4949
/// <summary>
5050
/// Program name of the app.
5151
/// </summary>
52-
protected const string ProgramApplicationAlias = "wingetcreate.exe";
52+
protected const string ProgramApplicationAlias = "wingetcreate";
5353

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

393-
if (success)
393+
if (result)
394394
{
395-
Logger.InfoLocalized(nameof(Resources.ManifestValidationSucceeded_Message), success);
395+
Logger.InfoLocalized(nameof(Resources.ManifestValidationSucceeded_Message), result);
396+
}
397+
else if (message == Constants.ManifestValidationUnavailable)
398+
{
399+
Logger.ErrorLocalized(nameof(Resources.ManifestValidationSucceeded_Message), message);
400+
Logger.WarnLocalized(nameof(Resources.ManifestValidationUnavailableOnUnix_Message));
396401
}
397402
else
398403
{
399-
Logger.ErrorLocalized(nameof(Resources.ManifestValidationSucceeded_Message), success);
404+
Logger.ErrorLocalized(nameof(Resources.ManifestValidationSucceeded_Message), result);
400405
Logger.Error(message);
401406
return false;
402407
}

src/WingetCreateCLI/Commands/SettingsCommand.cs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ namespace Microsoft.WingetCreateCLI.Commands
88
using System.ComponentModel;
99
using System.Diagnostics;
1010
using System.IO;
11+
using System.Runtime.InteropServices;
1112
using System.Threading.Tasks;
1213
using CommandLine;
1314
using Microsoft.WingetCreateCLI.Logging;
@@ -50,7 +51,7 @@ public override Task<bool> Execute()
5051
}
5152
else
5253
{
53-
this.DisplayParsingErrors(settingsFileErrors, UserSettings.SettingsJsonPath);
54+
DisplayParsingErrors(settingsFileErrors, UserSettings.SettingsJsonPath);
5455
}
5556
}
5657

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

6162
if (!isBackupValid)
6263
{
63-
this.DisplayParsingErrors(backupFileErrors, UserSettings.SettingsBackupJsonPath);
64+
DisplayParsingErrors(backupFileErrors, UserSettings.SettingsBackupJsonPath);
6465
}
6566
}
6667

67-
return Task.FromResult(commandEvent.IsSuccessful = this.OpenJsonFile(UserSettings.SettingsJsonPath));
68+
return Task.FromResult(commandEvent.IsSuccessful = OpenJsonFile(UserSettings.SettingsJsonPath));
6869
}
6970
finally
7071
{
7172
TelemetryManager.Log.WriteEvent(commandEvent);
7273
}
7374
}
7475

75-
private void DisplayParsingErrors(List<string> errors, string path)
76+
private static void DisplayParsingErrors(List<string> errors, string path)
7677
{
7778
Logger.WarnLocalized(nameof(Resources.ErrorParsingSettingsFile_Message), Path.GetFileName(path));
7879

@@ -83,7 +84,7 @@ private void DisplayParsingErrors(List<string> errors, string path)
8384
}
8485
}
8586

86-
private bool OpenJsonFile(string path)
87+
private static bool OpenJsonFile(string path)
8788
{
8889
if (!File.Exists(path))
8990
{
@@ -92,7 +93,23 @@ private bool OpenJsonFile(string path)
9293

9394
try
9495
{
95-
Process.Start(new ProcessStartInfo { UseShellExecute = true, FileName = path });
96+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
97+
{
98+
Process.Start(new ProcessStartInfo { UseShellExecute = true, FileName = path });
99+
}
100+
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
101+
{
102+
Process.Start("xdg-open", path);
103+
}
104+
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
105+
{
106+
Process.Start("open", path);
107+
}
108+
else
109+
{
110+
throw new PlatformNotSupportedException();
111+
}
112+
96113
return true;
97114
}
98115
catch (Win32Exception e)

0 commit comments

Comments
 (0)