Skip to content

Commit

Permalink
(chocolatey#310) Add Uninstall-ChocolateyPath as cmdlet
Browse files Browse the repository at this point in the history
Finally added Uninstall-ChocolateyPath. However, given overall contribution rates to the powershell functions are quite low, the decision has been made to rewrite our helper functions into C# cmdlets.

This serves as the initial set of cmdlets, a handful of useful example cases to prove out the viability of this approach, as well as ensuring that we have a better path forward for both OSS commands and any licensed commands we want to use in the future. It also opens up the possibility of more easily overriding the OSS cmdlets with a licensed command, and there are provisions in the `chocolateyInstaller.psm1` module script to ensure that can work seamlessly.

Summary of changes:

- Added Uninstall-ChocolateyPath helper cmdlet
- Rewrote the following associated functions into C# cmdlets:
  - Get-EnvironmentVariable
  - Get-EnvironmentVariableNames
  - Install-ChocolateyPath
  - Set-EnvironmentVariable
  - Test-ProcessAdminRights
  - Update-SessionEnvironment
- Tweaked the PowerShell command lookup behaviour when loading the `chocolateyInstaller.psm1` module to ensure that licensed cmdlets can be preferentially used instead of open-source cmdlets or functions, regardless of any name collisions that may occur.
- Tweaked the assembly resolver to ensure that if we have the licensed extension depend on the new Chocolatey.PowerShell assembly, it will not cause any issues when trying to load the licensed extension outside the PowerShell module context.
  • Loading branch information
vexx32 committed May 23, 2024
1 parent 118cb4b commit 2fcc425
Show file tree
Hide file tree
Showing 33 changed files with 1,426 additions and 1,888 deletions.
17 changes: 15 additions & 2 deletions nuspec/chocolatey/chocolatey/tools/chocolateysetup.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -463,8 +463,21 @@ function Install-ChocolateyFiles {
Get-ChildItem -Path "$_" | ForEach-Object {
#Write-Debug "Checking child path $_ ($($_.FullName))"
if (Test-Path $_.FullName) {
Write-Debug "Removing $_ unless matches .log"
Remove-Item $_.FullName -Exclude *.log -Recurse -Force -ErrorAction SilentlyContinue
# If this is an upgade, we can't *delete* Chocolatey.PowerShell.dll, as it will be currently loaded and thus locked.
# Instead, rename it with a .old suffix. The code in the installer module will delete the .old file next time it runs.
# This works similarly to how we move rather than overwriting choco.exe itself.
if ($_.Name -ne "Chocolatey.PowerShell.dll") {
Write-Debug "Removing $_ unless matches .log"
Remove-Item $_.FullName -Exclude *.log -Recurse -Force -ErrorAction SilentlyContinue
}
else {
$oldPath = "$($_.FullName).old"
Write-Debug "Moving $_ to $oldPath"

# Remove any still-existing Chocolatey.PowerShell.dll.old files before moving/renaming the current one.
Get-Item -Path $oldPath -ErrorAction SilentlyContinue | Remove-Item -Force
Move-Item $_.Fullname -Destination $oldPath
}
}
}
}
Expand Down
33 changes: 33 additions & 0 deletions nuspec/nuget/Chocolatey.PowerShell/Chocolatey.PowerShell.nuspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?xml version="1.0"?>
<package xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<metadata>
<id>Chocolatey.PowerShell</id>
<version>0.9.9</version>
<owners>Chocolatey Software, Inc</owners>
<title>Chocolatey CLI PowerShell Helpers</title>
<authors>Chocolatey Software, Inc</authors>
<projectUrl>https://github.com/chocolatey/choco</projectUrl>
<iconUrl>https://chocolatey.org/assets/images/nupkg/chocolateyicon.png</iconUrl>
<licenseUrl>https://raw.githubusercontent.com/chocolatey/choco/master/LICENSE</licenseUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<copyright>2024 Chocolatey Software, Inc</copyright>
<tags>chocolatey powershell</tags>
<summary>Chocolatey CLI's PowerShell helper commands</summary>
<description>
Chocolatey is a package manager for Windows (like apt-get but for Windows).

This is the Chocolatey PowerShell Library (API / DLL) package which contains the PowerShell helper commands used in Chocolatey CLI itself.

### Information

- [Chocolatey Website and Community Package Repository](https://community.chocolatey.org)
- [Mailing List](http://groups.google.com/group/chocolatey) / [Release Announcements Only Mailing List](https://groups.google.com/group/chocolatey-announce) / [Build Status Mailing List](http://groups.google.com/group/chocolatey-build-status)
- [Twitter](https://twitter.com/chocolateynuget) / [Facebook](https://www.facebook.com/ChocolateySoftware) / [GitHub](https://github.com/chocolatey)
- [Blog](https://blog.chocolatey.org/) / [Newsletter](https://chocolatey.us8.list-manage1.com/subscribe?u=86a6d80146a0da7f2223712e4&amp;id=73b018498d)
- [Documentation](https://docs.chocolatey.org/en-us/) / [Support](https://chocolatey.org/support)
</description>
<releaseNotes>
See all - https://docs.chocolatey.org/en-us/choco/release-notes
</releaseNotes>
</metadata>
</package>
35 changes: 24 additions & 11 deletions recipe.cake
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ Func<List<ILMergeConfig>> getILMergeConfigs = () =>
var targetPlatform = "v4,C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8";
var assembliesToILMerge = GetFiles(BuildParameters.Paths.Directories.PublishedApplications + "/choco/*.{exe|dll}")
- GetFiles(BuildParameters.Paths.Directories.PublishedApplications + "/choco/choco.exe")
- GetFiles(BuildParameters.Paths.Directories.PublishedApplications + "/choco/System.Management.Automation.dll");
- GetFiles(BuildParameters.Paths.Directories.PublishedApplications + "/choco/System.Management.Automation.dll")
- GetFiles(BuildParameters.Paths.Directories.PublishedApplications + "/choco/Chocolatey.PowerShell.dll");

Information("The following assemblies have been selected to be ILMerged for choco.exe...");
foreach (var assemblyToILMerge in assembliesToILMerge)
Expand All @@ -34,10 +35,11 @@ Func<List<ILMergeConfig>> getILMergeConfigs = () =>
AssemblyPaths = assembliesToILMerge });

assembliesToILMerge = GetFiles(BuildParameters.Paths.Directories.PublishedLibraries + "/chocolatey/*.{exe|dll}")
- GetFiles(BuildParameters.Paths.Directories.PublishedLibraries + "/chocolatey/choco.exe")
- GetFiles(BuildParameters.Paths.Directories.PublishedLibraries + "/chocolatey/chocolatey.dll")
- GetFiles(BuildParameters.Paths.Directories.PublishedLibraries + "/chocolatey/log4net.dll")
- GetFiles(BuildParameters.Paths.Directories.PublishedLibraries + "/chocolatey/System.Management.Automation.dll");
- GetFiles(BuildParameters.Paths.Directories.PublishedLibraries + "/chocolatey/choco.exe")
- GetFiles(BuildParameters.Paths.Directories.PublishedLibraries + "/chocolatey/chocolatey.dll")
- GetFiles(BuildParameters.Paths.Directories.PublishedLibraries + "/chocolatey/log4net.dll")
- GetFiles(BuildParameters.Paths.Directories.PublishedLibraries + "/chocolatey/System.Management.Automation.dll")
- GetFiles(BuildParameters.Paths.Directories.PublishedLibraries + "/chocolatey/Chocolatey.PowerShell.dll");

Information("The following assemblies have been selected to be ILMerged for chocolatey.dll...");
foreach (var assemblyToILMerge in assembliesToILMerge)
Expand All @@ -58,10 +60,11 @@ Func<List<ILMergeConfig>> getILMergeConfigs = () =>
if (DirectoryExists(BuildParameters.Paths.Directories.PublishedApplications + "/choco-no7zip/"))
{
var no7zAssembliesToILMerge = GetFiles(BuildParameters.Paths.Directories.PublishedApplications + "/choco-no7zip/*.{exe|dll}")
- GetFiles(BuildParameters.Paths.Directories.PublishedApplications + "/choco-no7zip/choco.exe")
- GetFiles(BuildParameters.Paths.Directories.PublishedApplications + "/choco-no7zip/System.Management.Automation.dll")
- GetFiles(BuildParameters.Paths.Directories.PublishedApplications + "/choco-no7zip/chocolatey.tests*.dll")
- GetFiles(BuildParameters.Paths.Directories.PublishedApplications + "/choco-no7zip/{Moq|nunit|Should|testcentric}*.dll");
- GetFiles(BuildParameters.Paths.Directories.PublishedApplications + "/choco-no7zip/choco.exe")
- GetFiles(BuildParameters.Paths.Directories.PublishedApplications + "/choco-no7zip/System.Management.Automation.dll")
- GetFiles(BuildParameters.Paths.Directories.PublishedApplications + "/choco-no7zip/chocolatey.tests*.dll")
- GetFiles(BuildParameters.Paths.Directories.PublishedApplications + "/choco-no7zip/{Moq|nunit|Should|testcentric}*.dll")
- GetFiles(BuildParameters.Paths.Directories.PublishedApplications + "/choco-no7zip/Chocolatey.PowerShell.dll");

Information("The following assemblies have been selected to be ILMerged for choco.exe No7zip Version...");
foreach (var assemblyToILMerge in no7zAssembliesToILMerge)
Expand Down Expand Up @@ -121,13 +124,15 @@ Func<FilePathCollection> getFilesToSign = () =>
var filesToSign = GetFiles(BuildParameters.Paths.Directories.NuGetNuspecDirectory + "/lib/chocolatey.dll")
+ GetFiles(BuildParameters.Paths.Directories.ChocolateyNuspecDirectory + "/tools/chocolateyInstall/choco.exe")
+ GetFiles(BuildParameters.Paths.Directories.ChocolateyNuspecDirectory + "/tools/chocolateyInstall/tools/{checksum|shimgen}.exe")
+ GetFiles(BuildParameters.Paths.Directories.ChocolateyNuspecDirectory + "/tools/chocolateyInstall/redirects/*.exe");
+ GetFiles(BuildParameters.Paths.Directories.ChocolateyNuspecDirectory + "/tools/chocolateyInstall/redirects/*.exe")
+ GetFiles(BuildParameters.Paths.Directories.ChocolateyNuspecDirectory + "/tools/chocolateyInstall/helpers/Chocolatey.PowerShell.dll");

if (DirectoryExists(BuildParameters.Paths.Directories.ChocolateyNuspecDirectory + "-no7zip"))
{
filesToSign += GetFiles(BuildParameters.Paths.Directories.ChocolateyNuspecDirectory + "-no7zip/tools/chocolateyInstall/choco.exe")
+ GetFiles(BuildParameters.Paths.Directories.ChocolateyNuspecDirectory + "-no7zip/tools/chocolateyInstall/tools/{checksum|shimgen}.exe")
+ GetFiles(BuildParameters.Paths.Directories.ChocolateyNuspecDirectory + "-no7zip/tools/chocolateyInstall/redirects/*.exe");
+ GetFiles(BuildParameters.Paths.Directories.ChocolateyNuspecDirectory + "-no7zip/tools/chocolateyInstall/redirects/*.exe")
+ GetFiles(BuildParameters.Paths.Directories.ChocolateyNuspecDirectory + "-no7zip/tools/chocolateyInstall/helpers/Chocolatey.PowerShell.dll");
}

Information("The following assemblies have been selected to be signed...");
Expand Down Expand Up @@ -172,6 +177,10 @@ Task("Prepare-Chocolatey-Packages")

StartProcess(BuildParameters.Paths.Directories.ChocolateyNuspecDirectory + "/tools/chocolateyInstall/choco.exe", new ProcessSettings{ Arguments = "unpackself -f -y --allow-unofficial-build --run-actual" });

// Copy Chocolatey.PowerShell.dll and its help.xml file
CopyFile(BuildParameters.Paths.Directories.PublishedLibraries + "/Chocolatey.PowerShell/Chocolatey.PowerShell.dll", BuildParameters.Paths.Directories.ChocolateyNuspecDirectory + "/tools/chocolateyInstall/helpers/Chocolatey.PowerShell.dll");
CopyFile(BuildParameters.Paths.Directories.PublishedLibraries + "/Chocolatey.PowerShell/Chocolatey.PowerShell.dll-help.xml", BuildParameters.Paths.Directories.ChocolateyNuspecDirectory + "/tools/chocolateyInstall/helpers/Chocolatey.PowerShell.dll-help.xml");

// Tidy up logs and config folder which are not required
var logsDirectory = BuildParameters.Paths.Directories.ChocolateyNuspecDirectory + "/tools/chocolateyInstall/logs";
var configDirectory = BuildParameters.Paths.Directories.ChocolateyNuspecDirectory + "/tools/chocolateyInstall/config";
Expand Down Expand Up @@ -260,6 +269,10 @@ Task("Prepare-ChocolateyNo7zip-Package")

StartProcess(nuspecDirectory + "/tools/chocolateyInstall/choco.exe", new ProcessSettings{ Arguments = "unpackself -f -y --allow-unofficial-build" });

// Copy Chocolatey.PowerShell.dll and help.xml file
CopyFile(BuildParameters.Paths.Directories.PublishedLibraries + "/Chocolatey.PowerShell/Chocolatey.PowerShell.dll", nuspecDirectory + "/tools/chocolateyInstall/helpers/Chocolatey.PowerShell.dll");
CopyFile(BuildParameters.Paths.Directories.PublishedLibraries + "/Chocolatey.PowerShell/Chocolatey.PowerShell.dll-help.xml", nuspecDirectory + "/tools/chocolateyInstall/helpers/Chocolatey.PowerShell.dll-help.xml");

// Tidy up logs and config folder which are not required
var logsDirectory = nuspecDirectory + "/tools/chocolateyInstall/logs";
var configDirectory = nuspecDirectory + "/tools/chocolateyInstall/config";
Expand Down
82 changes: 82 additions & 0 deletions src/Chocolatey.PowerShell/Chocolatey.PowerShell.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{88396C46-8089-4814-A7D1-E18777FF6083}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Chocolatey.PowerShell</RootNamespace>
<AssemblyName>Chocolatey.PowerShell</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<LangVersion>7.3</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseOfficial|AnyCPU' or '$(Configuration)|$(Platform)' == 'ReleaseOfficialNo7zip|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ReleaseOfficial\</OutputPath>
<DefineConstants>TRACE;FORCE_CHOCOLATEY_OFFICIAL_KEY</DefineConstants>
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="System.Management.Automation">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\lib\PowerShell\System.Management.Automation.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Commands\GetEnvironmentVariableCommand.cs" />
<Compile Include="Commands\GetEnvironmentVariableNamesCommand.cs" />
<Compile Include="Commands\InstallChocolateyPathCommand.cs" />
<Compile Include="Commands\SetEnvironmentVariableCommand.cs" />
<Compile Include="Commands\TestProcessAdminRightsCommand.cs" />
<Compile Include="Commands\UninstallChocolateyPathCommand.cs" />
<Compile Include="Commands\UpdateSessionEnvironmentCommand.cs" />
<Compile Include="Helpers\Elevation.cs" />
<Compile Include="Helpers\EnvironmentHelper.cs" />
<Compile Include="Helpers\Paths.cs" />
<Compile Include="Helpers\ProcessInformation.cs" />
<Compile Include="Helpers\PSHelper.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="..\SolutionVersion.cs">
<Link>Properties\SolutionVersion.cs</Link>
</Compile>
<Compile Include="Shared\ChocolateyCmdlet.cs" />
<Compile Include="Shared\EnvironmentVariables.cs" />
<Compile Include="Win32\NativeMethods.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright © 2017 - 2024 Chocolatey Software, Inc
// Copyright © 2011 - 2017 RealDimensions Software, LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
//
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using System.Management.Automation;
using Chocolatey.PowerShell.Helpers;
using Chocolatey.PowerShell.Shared;

namespace Chocolatey.PowerShell.Commands
{
[Cmdlet(VerbsCommon.Get, "EnvironmentVariable")]
[OutputType(typeof(string))]
public sealed class GetEnvironmentVariableCommand : ChocolateyCmdlet
{
[Parameter(Mandatory = true, Position = 0)]
public string Name { get; set; }

[Parameter(Mandatory = true, Position = 1)]
public EnvironmentVariableTarget Scope { get; set; }

[Parameter]
public SwitchParameter PreserveVariables { get; set; }

// Avoid logging environment variable names by accident.
protected override bool Logging { get; } = false;

protected override void End()
{
if (PreserveVariables)
{
WriteVerbose("Choosing not to expand environment names");
}

WriteObject(EnvironmentHelper.GetVariable(this, Name, Scope, PreserveVariables));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright © 2017 - 2024 Chocolatey Software, Inc
// Copyright © 2011 - 2017 RealDimensions Software, LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
//
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using System.Management.Automation;
using Chocolatey.PowerShell.Helpers;
using Chocolatey.PowerShell.Shared;

namespace Chocolatey.PowerShell.Commands
{
[Cmdlet(VerbsCommon.Get, "EnvironmentVariableNames")]
[OutputType(typeof(string))]
public class GetEnvironmentVariableNamesCommand : ChocolateyCmdlet
{
[Parameter(Position = 0)]
public EnvironmentVariableTarget Scope { get; set; }

// Do not log function call
protected override bool Logging { get; } = false;


protected override void End()
{
WriteObject(EnvironmentHelper.GetVariableNames(Scope));
}
}
}
Loading

0 comments on commit 2fcc425

Please sign in to comment.