Skip to content
Merged
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
16 changes: 1 addition & 15 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ jobs:
buildOutDirAnyCpu: $(Build.SourcesDirectory)\src\AnyCPU\$(buildConfiguration)
artifactsDir: $(Build.ArtifactStagingDirectory)\$(buildPlatform)
appxPackageDir: $(Build.ArtifactStagingDirectory)\$(buildPlatform)\AppxPackages
packageLayoutDir: $(Build.BinariesDirectory)\WingetPackageLayout

steps:
- task: NuGetToolInstaller@1
Expand Down Expand Up @@ -153,7 +152,6 @@ jobs:
displayName: 'Copy specific build artifacts'
inputs:
Contents: |
$(buildOutDir)\WindowsPackageManager\WindowsPackageManager.pdb
$(buildOutDir)\WinGetUtil\WinGetUtil.dll
$(buildOutDir)\WinGetUtil\WinGetUtil.pdb
TargetFolder: '$(artifactsDir)'
Expand All @@ -162,21 +160,9 @@ jobs:
displayName: Create Package Layout
inputs:
filePath: 'src\AppInstallerCLIPackage\Execute-AppxRecipe.ps1'
arguments: '-AppxRecipePath AppInstallerCLIPackage\bin\$(buildPlatform)\$(buildConfiguration)\AppInstallerCLIPackage.build.appxrecipe -LayoutPath $(packageLayoutDir) -Force -Verbose'
arguments: '-AppxRecipePath AppInstallerCLIPackage\bin\$(buildPlatform)\$(buildConfiguration)\AppInstallerCLIPackage.build.appxrecipe -LayoutPath $(artifactsDir)\DevPackage -Force -Verbose'
workingDirectory: 'src'

- task: CopyFiles@2
displayName: 'Copy Dev Package (Loose Files)'
inputs:
SourceFolder: '$(packageLayoutDir)'
TargetFolder: '$(artifactsDir)\DevPackage'

- task: DeleteFiles@1
displayName: Clean up Package Layout after copy
inputs:
SourceFolder: '$(packageLayoutDir)'
Contents: '**/*'

- task: CopyFiles@2
displayName: 'Copy native binaries for Microsoft.WinGet.Client (net8)'
inputs:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0-windows10.0.26100.0</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<SupportedOSPlatformVersion>10.0.17763.0</SupportedOSPlatformVersion>
Expand Down
37 changes: 36 additions & 1 deletion src/ConfigurationRemotingServer/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
using System.Text.Json.Serialization;
using Microsoft.Management.Configuration;
using Microsoft.Management.Configuration.Processor;
using Microsoft.Management.Configuration.Processor.Helpers;
using Microsoft.Win32;
using WinRT;
using IConfigurationSetProcessorFactory = global::Microsoft.Management.Configuration.IConfigurationSetProcessorFactory;

Expand Down Expand Up @@ -79,6 +81,18 @@ static int Main(string[] args)

string staticsCallback = args[1];

// Listen for setting change message and update PATH if needed.
HiddenForm hiddenForm = new HiddenForm();
var settingChangedListenerThread = new Thread(
() =>
{
SystemEvents.UserPreferenceChanged += OnUserPreferenceChanged;
Application.Run(hiddenForm);
SystemEvents.UserPreferenceChanged -= OnUserPreferenceChanged;
});

settingChangedListenerThread.Start();

try
{
string completionEventName = args[2];
Expand Down Expand Up @@ -147,11 +161,32 @@ static int Main(string[] args)

return WindowsPackageManagerConfigurationCompleteOutOfProcessFactoryInitialization(0, factoryInterface.ThisPtr, staticsCallback, completionEventName, parentProcessId);
}
catch(Exception ex)
catch (Exception ex)
{
WindowsPackageManagerConfigurationCompleteOutOfProcessFactoryInitialization(ex.HResult, IntPtr.Zero, staticsCallback, null, 0);
return ex.HResult;
}
finally
{
hiddenForm.BeginInvoke(new Action(() => { hiddenForm.Close(); }));
settingChangedListenerThread.Join();
}
}

private class HiddenForm : Form
{
public HiddenForm()
{
this.Width = 0;
this.Height = 0;
this.Visible = false;
this.Load += (sender, e) => this.Hide();
}
}

private static void OnUserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)
{
PathEnvironmentVariableHandler.UpdatePath();
}

private class LimitationSetMetadata
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace Microsoft.Management.Configuration.Processor.DSCv3.Helpers
using System.Diagnostics;
using System.Text;
using System.Threading;
using Microsoft.Management.Configuration.Processor.Helpers;

/// <summary>
/// Wrapper for a single process execution and its output.
Expand Down Expand Up @@ -134,7 +135,13 @@ public ProcessExecution Start()
throw new InvalidOperationException("Process has already been started.");
}

ProcessStartInfo startInfo = new ProcessStartInfo(this.ExecutablePath, this.SerializedArguments);
ProcessStartInfo startInfo;

lock (PathEnvironmentVariableHandler.Lock)
{
startInfo = new ProcessStartInfo(this.ExecutablePath, this.SerializedArguments);
}

this.Process = new Process() { StartInfo = startInfo };

startInfo.UseShellExecute = false;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// -----------------------------------------------------------------------------
// <copyright file="PathEnvironmentVariableHandler.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
// </copyright>
// -----------------------------------------------------------------------------

namespace Microsoft.Management.Configuration.Processor.Helpers
{
using System;
using System.Collections.Generic;

/// <summary>
/// Class for handling PATH environment variable.
/// </summary>
public static class PathEnvironmentVariableHandler
{
private const string PathEnvironmentVariable = "PATH";

private static readonly object EnvironmentVariableLock = new object();

/// <summary>
/// Gets the lock to read or write PATH environment variable.
/// </summary>
public static object Lock
{
get { return EnvironmentVariableLock; }
}

/// <summary>
/// Updates the process's PATH environment variable if new paths added.
/// Only adds new paths since we add to PATH in other code which may not be in the registry.
/// </summary>
public static void UpdatePath()
{
HashSet<string> paths = new HashSet<string>(Environment.GetEnvironmentVariable(PathEnvironmentVariable)?.Split(';') ?? Array.Empty<string>());
var originalPathsSize = paths.Count;

AddPathsIfNotExist(paths, Environment.GetEnvironmentVariable(PathEnvironmentVariable, EnvironmentVariableTarget.Machine)?.Split(';'));
AddPathsIfNotExist(paths, Environment.GetEnvironmentVariable(PathEnvironmentVariable, EnvironmentVariableTarget.User)?.Split(';'));

if (paths.Count > originalPathsSize)
{
lock (Lock)
{
Environment.SetEnvironmentVariable(PathEnvironmentVariable, string.Join(';', paths));
}
}
}

// TODO: Currently it always adds new paths to the end. The "proper" thing to do would probably be to calculate
// the full new list of paths (what one would expect to get from a new process launch) and use a line merge algorithm
// with a strategy that puts the ephemeral entries before the new permanent ones.
#pragma warning disable SA1011 // Closing square brackets should be spaced correctly
private static void AddPathsIfNotExist(HashSet<string> currentPaths, string[]? paths)
#pragma warning restore SA1011 // Closing square brackets should be spaced correctly
{
if (paths is not null)
{
foreach (var path in paths)
{
if (!currentPaths.Contains(path))
{
currentPaths.Add(path);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This always adds to the end, making it the last location to look. That may cause issues in some corner case; probably ok for now but maybe add a comment.

The "proper" thing to do would probably be to calculate the full new list of paths (what one would expect to get from a new process launch) and use a line merge algorithm with a strategy that puts the ephemeral entries before the new permanent ones. But that is a fair bit more complicated and could wait until later.

}
}
}
}
}
}
Loading