diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 6ad155756b5..a3dc6fd5198 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -11,35 +11,35 @@ ## PR Checklist - [ ] [PR has a meaningful title](https://github.com/PowerShell/PowerShell/blob/master/.github/CONTRIBUTING.md#pull-request---submission) - - Use the present tense and imperative mood when describing your changes + - Use the present tense and imperative mood when describing your changes - [ ] [Summarized changes](https://github.com/PowerShell/PowerShell/blob/master/.github/CONTRIBUTING.md#pull-request---submission) - [ ] [Make sure all `.h`, `.cpp`, `.cs`, `.ps1` and `.psm1` files have the correct copyright header](https://github.com/PowerShell/PowerShell/blob/master/.github/CONTRIBUTING.md#pull-request---submission) - [ ] This PR is ready to merge and is not [Work in Progress](https://github.com/PowerShell/PowerShell/blob/master/.github/CONTRIBUTING.md#pull-request---work-in-progress). - - If the PR is work in progress, please add the prefix `WIP:` or `[ WIP ]` to the beginning of the title (the `WIP` bot will keep its status check at `Pending` while the prefix is present) and remove the prefix when the PR is ready. + - If the PR is work in progress, please add the prefix `WIP:` or `[ WIP ]` to the beginning of the title (the `WIP` bot will keep its status check at `Pending` while the prefix is present) and remove the prefix when the PR is ready. - **[Breaking changes](https://github.com/PowerShell/PowerShell/blob/master/.github/CONTRIBUTING.md#making-breaking-changes)** - - [ ] None - - **OR** - - [ ] [Experimental feature(s) needed](https://github.com/MicrosoftDocs/PowerShell-Docs/blob/main/reference/7.3/Microsoft.PowerShell.Core/About/about_Experimental_Features.md) - - [ ] Experimental feature name(s): + - [ ] None + - **OR** + - [ ] [Experimental feature(s) needed](https://github.com/MicrosoftDocs/PowerShell-Docs/blob/main/reference/7.5/Microsoft.PowerShell.Core/About/about_Experimental_Features.md) + - [ ] Experimental feature name(s): - **User-facing changes** - - [ ] Not Applicable - - **OR** - - [ ] [Documentation needed](https://github.com/PowerShell/PowerShell/blob/master/.github/CONTRIBUTING.md#pull-request---submission) + - [ ] Not Applicable + - **OR** + - [ ] [Documentation needed](https://github.com/PowerShell/PowerShell/blob/master/.github/CONTRIBUTING.md#pull-request---submission) - [ ] Issue filed: - **Testing - New and feature** - - [ ] N/A or can only be tested interactively - - **OR** - - [ ] [Make sure you've added a new test if existing tests do not effectively test the code changed](https://github.com/PowerShell/PowerShell/blob/master/.github/CONTRIBUTING.md#before-submitting) + - [ ] N/A or can only be tested interactively + - **OR** + - [ ] [Make sure you've added a new test if existing tests do not effectively test the code changed](https://github.com/PowerShell/PowerShell/blob/master/.github/CONTRIBUTING.md#before-submitting) - **Tooling** - - [ ] I have considered the user experience from a tooling perspective and don't believe tooling will be impacted. - - **OR** - - [ ] I have considered the user experience from a tooling perspective and opened an issue in the relevant tool repository. This may include: - - [ ] Impact on [PowerShell Editor Services](https://github.com/PowerShell/PowerShellEditorServices) which is used in the [PowerShell extension](https://github.com/PowerShell/vscode-powershell) for VSCode + - [ ] I have considered the user experience from a tooling perspective and don't believe tooling will be impacted. + - **OR** + - [ ] I have considered the user experience from a tooling perspective and opened an issue in the relevant tool repository. This may include: + - [ ] Impact on [PowerShell Editor Services](https://github.com/PowerShell/PowerShellEditorServices) which is used in the [PowerShell extension](https://github.com/PowerShell/vscode-powershell) for VSCode (which runs in a different PS Host). - - [ ] Issue filed: - - [ ] Impact on Completions (both in the console and in editors) - one of PowerShell's most powerful features. - - [ ] Issue filed: - - [ ] Impact on [PSScriptAnalyzer](https://github.com/PowerShell/PSScriptAnalyzer) (which provides linting & formatting in the editor extensions). - - [ ] Issue filed: - - [ ] Impact on [EditorSyntax](https://github.com/PowerShell/EditorSyntax) (which provides syntax highlighting with in VSCode, GitHub, and many other editors). - - [ ] Issue filed: + - [ ] Issue filed: + - [ ] Impact on Completions (both in the console and in editors) - one of PowerShell's most powerful features. + - [ ] Issue filed: + - [ ] Impact on [PSScriptAnalyzer](https://github.com/PowerShell/PSScriptAnalyzer) (which provides linting & formatting in the editor extensions). + - [ ] Issue filed: + - [ ] Impact on [EditorSyntax](https://github.com/PowerShell/EditorSyntax) (which provides syntax highlighting with in VSCode, GitHub, and many other editors). + - [ ] Issue filed: diff --git a/.pipelines/PowerShell-Coordinated_Packages-Official.yml b/.pipelines/PowerShell-Coordinated_Packages-Official.yml index 81c74e66d29..b1a268a097d 100644 --- a/.pipelines/PowerShell-Coordinated_Packages-Official.yml +++ b/.pipelines/PowerShell-Coordinated_Packages-Official.yml @@ -64,6 +64,11 @@ variables: extends: template: v2/OneBranch.Official.CrossPlat.yml@onebranchTemplates parameters: + featureFlags: + LinuxHostVersion: + Network: KS2 + WindowsHostVersion: + Network: KS2 customTags: 'ES365AIMigrationTooling' globalSdl: disableLegacyManifest: true diff --git a/.pipelines/templates/linux-package-build.yml b/.pipelines/templates/linux-package-build.yml index f312fbe31bb..7e62087a87a 100644 --- a/.pipelines/templates/linux-package-build.yml +++ b/.pipelines/templates/linux-package-build.yml @@ -36,6 +36,8 @@ jobs: value: $(Build.SourcesDirectory)/PowerShell/.config/tsaoptions.json - name: ob_sdl_credscan_suppressionsFile value: $(Build.SourcesDirectory)/PowerShell/.config/suppress.json + - name: SigningProfile + value: ${{ parameters.signingProfile }} steps: - checkout: self @@ -174,7 +176,7 @@ jobs: displayName: Sign deb and rpm packages inputs: command: 'sign' - signing_profile: CP-459159-pgpdetached + signing_profile: '$(SigningProfile)' files_to_sign: '**/*.rpm;**/*.deb' search_root: '$(Pipeline.Workspace)' diff --git a/.vsts-ci/linux.yml b/.vsts-ci/linux.yml index 57c60bc25a7..cd863696d55 100644 --- a/.vsts-ci/linux.yml +++ b/.vsts-ci/linux.yml @@ -23,6 +23,7 @@ trigger: - .vsts-ci/misc-analysis.yml - .github/ISSUE_TEMPLATE/* - .dependabot/config.yml + - .pipelines/* - test/perf/* pr: branches: @@ -48,6 +49,7 @@ pr: - tools/releaseBuild/azureDevOps/templates/* - README.md - .spelling + - .pipelines/* variables: DOTNET_CLI_TELEMETRY_OPTOUT: 1 diff --git a/.vsts-ci/mac.yml b/.vsts-ci/mac.yml index 4f5e999a335..0d17c4d765c 100644 --- a/.vsts-ci/mac.yml +++ b/.vsts-ci/mac.yml @@ -15,6 +15,7 @@ trigger: - .vsts-ci/misc-analysis.yml - .github/ISSUE_TEMPLATE/* - .dependabot/config.yml + - .pipelines/* - test/perf/* pr: branches: @@ -40,6 +41,7 @@ pr: - tools/releaseBuild/azureDevOps/templates/* - README.md - .spelling + - .pipelines/* variables: DOTNET_CLI_TELEMETRY_OPTOUT: 1 diff --git a/.vsts-ci/windows.yml b/.vsts-ci/windows.yml index c3a39647852..b505c9ed04e 100644 --- a/.vsts-ci/windows.yml +++ b/.vsts-ci/windows.yml @@ -15,6 +15,7 @@ trigger: - .github/ISSUE_TEMPLATE/* - .dependabot/config.yml - test/perf/* + - .pipelines/* pr: branches: include: @@ -37,6 +38,7 @@ pr: - tools/releaseBuild/azureDevOps/templates/* - README.md - .spelling + - .pipelines/* variables: GIT_CONFIG_PARAMETERS: "'core.autocrlf=false'" diff --git a/CHANGELOG/7.4.md b/CHANGELOG/7.4.md index e947578b89e..204b81512ff 100644 --- a/CHANGELOG/7.4.md +++ b/CHANGELOG/7.4.md @@ -1,5 +1,45 @@ # 7.4 Changelog +## [7.4.5] - 2024-08-20 + +### General Cmdlet Updates and Fixes + +- Fix WebCmdlets when `-Body` is specified but `ContentType` is not (#24145) + +### Tests + +- Rewrite the mac syslog tests to make them less flaky (#24152) + +### Build and Packaging Improvements + +
+ + + +

Bump .NET SDK to 8.0.400

+ +
+ + + +
+ +### Documentation and Help Content + +- Update docs sample nuget.config (#24147) +- Fix up broken links in Markdown files (#24144) + +[7.4.5]: https://github.com/PowerShell/PowerShell/compare/v7.4.4...v7.4.5 + ## [7.4.4] - 2024-07-18 ### Engine Updates and Fixes diff --git a/CHANGELOG/preview.md b/CHANGELOG/preview.md new file mode 100644 index 00000000000..28605544ff7 --- /dev/null +++ b/CHANGELOG/preview.md @@ -0,0 +1,3 @@ +# Preview Changelog + +Information about PowerShell previews will be found in this file diff --git a/ThirdPartyNotices.txt b/ThirdPartyNotices.txt index ebfcf9a5287..1cc2452a065 100644 --- a/ThirdPartyNotices.txt +++ b/ThirdPartyNotices.txt @@ -285,7 +285,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI --------------------------------------------------------- -Microsoft.Extensions.ObjectPool 8.0.7 - MIT +Microsoft.Extensions.ObjectPool 8.0.8 - MIT Copyright 2019 The gRPC @@ -656,7 +656,7 @@ SOFTWARE. --------------------------------------------------------- -Microsoft.Windows.Compatibility 8.0.7 - MIT +Microsoft.Windows.Compatibility 8.0.8 - MIT (c) Microsoft Corporation @@ -2444,12 +2444,9 @@ SOFTWARE. --------------------------------------------------------- -System.Drawing.Common 8.0.7 - MIT +System.Drawing.Common 8.0.8 - MIT -(c) Microsoft Corporation -Copyright (c) Sven Groot (Ookii.org) 2009 -Copyright (c) .NET Foundation and Contributors The MIT License (MIT) @@ -2823,7 +2820,7 @@ SOFTWARE. --------------------------------------------------------- -System.Net.Http.WinHttpHandler 8.0.1 - MIT +System.Net.Http.WinHttpHandler 8.0.2 - MIT Copyright (c) Six Labors diff --git a/assets/wix/Product.wxs b/assets/wix/Product.wxs index b2cb57dbdd2..0b525288ae1 100644 --- a/assets/wix/Product.wxs +++ b/assets/wix/Product.wxs @@ -44,6 +44,12 @@ + + + + + + + + + + + + + + + + not INSTALLFOLDER and PREVIOUS_INSTALLFOLDER + + + + + + + + not ADD_PATH and PREVIOUS_ADD_PATH + + + not ADD_PATH + + + ADD_PATH<>1 + + + not ADD_PATH + + + + + + + + not REGISTER_MANIFEST and PREVIOUS_REGISTER_MANIFEST + + + not REGISTER_MANIFEST + + + REGISTER_MANIFEST<>1 + + + not REGISTER_MANIFEST + + + + + + + + not ENABLE_PSREMOTING and PREVIOUS_ENABLE_PSREMOTING + + + ENABLE_PSREMOTING<>1 + + + not ENABLE_PSREMOTING + + + + + + + + not DISABLE_TELEMETRY and PREVIOUS_DISABLE_TELEMETRY + + + DISABLE_TELEMETRY<>1 + + + not DISABLE_TELEMETRY + + + + + + + + not ADD_EXPLORER_CONTEXT_MENU_OPENPOWERSHELL and PREVIOUS_ADD_EXPLORER_CONTEXT_MENU_OPENPOWERSHELL + + + ADD_EXPLORER_CONTEXT_MENU_OPENPOWERSHELL<>1 + + + not ADD_EXPLORER_CONTEXT_MENU_OPENPOWERSHELL + + + + + + + + not ADD_FILE_CONTEXT_MENU_RUNPOWERSHELL and PREVIOUS_ADD_FILE_CONTEXT_MENU_RUNPOWERSHELL + + + ADD_FILE_CONTEXT_MENU_RUNPOWERSHELL<>1 + + + not ADD_FILE_CONTEXT_MENU_RUNPOWERSHELL + + + + + + + + not USE_MU and PREVIOUS_USE_MU + + + not USE_MU + + + USE_MU<>1 + + + not USE_MU + + + + + + + + not ENABLE_MU and PREVIOUS_ENABLE_MU + + + not ENABLE_MU + + + ENABLE_MU<>1 + + + not ENABLE_MU + + + + + @@ -230,7 +403,7 @@ - DISABLE_TELEMETRY + DISABLE_TELEMETRY=1 @@ -245,7 +418,7 @@ - ADD_EXPLORER_CONTEXT_MENU_OPENPOWERSHELL + ADD_EXPLORER_CONTEXT_MENU_OPENPOWERSHELL=1 @@ -295,7 +468,7 @@ - ADD_FILE_CONTEXT_MENU_RUNPOWERSHELL + ADD_FILE_CONTEXT_MENU_RUNPOWERSHELL=1 @@ -305,6 +478,17 @@ + + + + + + + + + + + @@ -328,8 +512,6 @@ - - @@ -337,12 +519,12 @@ - - - - - - + + + + + + The application is distributed under the MIT license.]]> @@ -363,8 +545,6 @@ - - diff --git a/docs/cmdlet-example/visual-studio-simple-example.md b/docs/cmdlet-example/visual-studio-simple-example.md index b4a20ba138c..37244f25705 100644 --- a/docs/cmdlet-example/visual-studio-simple-example.md +++ b/docs/cmdlet-example/visual-studio-simple-example.md @@ -131,5 +131,5 @@ It should find `PowerShellStandard.Library` package, select it and it will show ![StdImage61](./Images/Std61.png) On PowerShell Core on Linux: ![StdImage62](./Images/Std62.png) -On Windows PowerShell on Windows (this requires [.NET Framework 4.7.1](https://github.com/Microsoft/dotnet-framework-early-access/blob/master/instructions.md)): +On Windows PowerShell on Windows (this requires [.NET Framework 4.7.1](https://dotnet.microsoft.com/en-us/download/dotnet-framework/net471) ![StdImage63](./Images/Std63.png) diff --git a/docs/git/README.md b/docs/git/README.md index 817e4930f6c..46b5eee4c62 100644 --- a/docs/git/README.md +++ b/docs/git/README.md @@ -13,9 +13,9 @@ git clone https://github.com/PowerShell/PowerShell.git --branch=master * Checkout a new local branch from `master` for every change you want to make (bugfix, feature). * Use lowercase-with-dashes for naming. * Follow [Linus' recommendations][Linus] about history. - - "People can (and probably should) rebase their _private_ trees (their own work). That's a _cleanup_. But never other peoples code. That's a 'destroy history'... - You must never EVER destroy other peoples history. You must not rebase commits other people did. - Basically, if it doesn't have your sign-off on it, it's off limits: you can't rebase it, because it's not yours." + * "People can (and probably should) rebase their _private_ trees (their own work). That's a _cleanup_. But never other peoples code. That's a 'destroy history'... + You must never EVER destroy other peoples history. You must not rebase commits other people did. + Basically, if it doesn't have your sign-off on it, it's off limits: you can't rebase it, because it's not yours." ### Understand branches @@ -23,12 +23,12 @@ git clone https://github.com/PowerShell/PowerShell.git --branch=master It could be unstable. * Send your pull requests to **master**. -### Sync your local repo +### Sync your local repository Use **git rebase** instead of **git merge** and **git pull**, when you're updating your feature-branch. ```sh -# fetch updates all remote branch references in the repo +# fetch updates all remote branch references in the repository # --all : tells it to do it for all remotes (handy, when you use your fork) # -p : tells it to remove obsolete remote branch references (when they are removed from remote) git fetch --all -p @@ -42,11 +42,9 @@ git rebase origin/master Covering all possible git scenarios is behind the scope of the current document. Git has excellent documentation and lots of materials available online. -We are leaving few links here: +We are leaving a few links here: -[Git pretty flowchart](http://justinhileman.info/article/git-pretty/): what to do, when your local repo became a mess. - -[Linus]:https://wincent.com/wiki/git_rebase%3A_you're_doing_it_wrong +[Linus]:https://web.archive.org/web/20230522041845/https://wincent.com/wiki/git_rebase%3A_you're_doing_it_wrong ## Tags @@ -57,12 +55,12 @@ you will find it via **tags**. * Find the tag that corresponds to the release. * Use `git checkout ` to get this version. -**Note:** [checking out a tag][tag] will move the repo to a [DETACHED HEAD][HEAD] state. +**Note:** [checking out a tag][tag] will move the repository to a [DETACHED HEAD][HEAD] state. [tag]:https://git-scm.com/book/en/v2/Git-Basics-Tagging#Checking-out-Tags [HEAD]:https://www.git-tower.com/learn/git/faq/detached-head-when-checkout-commit -If you want to make changes, based on tag's version (i.e. a hotfix), +If you want to make changes, based on tag's version (i.e. a hotfix), checkout a new branch from this DETACHED HEAD state. ```sh diff --git a/docs/host-powershell/sample/NuGet.config b/docs/host-powershell/sample/NuGet.config.md similarity index 70% rename from docs/host-powershell/sample/NuGet.config rename to docs/host-powershell/sample/NuGet.config.md index b3ce3cb82a5..bf2b4c3f688 100644 --- a/docs/host-powershell/sample/NuGet.config +++ b/docs/host-powershell/sample/NuGet.config.md @@ -1,3 +1,8 @@ +# Nuget.config creation + +Create a filed called `nuget.config` at this location with this content: + +```xml @@ -8,3 +13,4 @@ +``` diff --git a/docs/maintainers/releasing.md b/docs/maintainers/releasing.md index a44ae5ee604..5aae87582c9 100644 --- a/docs/maintainers/releasing.md +++ b/docs/maintainers/releasing.md @@ -21,20 +21,15 @@ This is to help track the release preparation work. - Sign the MSI packages and DEB/RPM packages. - Install and verify the packages. 1. Update documentation, scripts and Dockerfiles - - Summarize the change log for the release. It should be reviewed by PM(s) to make it more user-friendly. - - Update [CHANGELOG.md](../../CHANGELOG.md) with the finalized change log draft. + - Summarize the changelog for the release. It should be reviewed by PM(s) to make it more user-friendly. + - Update [CHANGELOG.md](../../CHANGELOG.md) with the finalized changelog draft. - Update other documents and scripts to use the new package names and links. 1. Verify the release Dockerfiles. 1. [Create NuGet packages](#nuget-packages) and publish them to [powershell-core feed][ps-core-feed]. 1. [Create the release tag](#release-tag) and push the tag to `PowerShell/PowerShell` repository. -1. Create the draft and publish the release in Github. +1. Create the draft and publish the release in GitHub. 1. Merge the `release-` branch to `master` in `powershell/powershell` and delete the `release-` branch. 1. Publish Linux packages to Microsoft YUM/APT repositories. -1. Trigger the release docker builds for Linux and Windows container images. - - Linux: push a branch named `docker` to `powershell/powershell` repository to trigger the build at [powershell docker hub](https://hub.docker.com/r/microsoft/powershell/builds/). - Delete the `docker` branch once the builds succeed. - - Windows: queue a new build in `PowerShell Windows Docker Build` on VSTS. -1. Verify the generated docker container images. 1. [Update the homebrew formula](#homebrew) for the macOS package. This task usually will be taken care of by the community, so we can wait for one day or two and see if the homebrew formula has already been updated, @@ -104,7 +99,7 @@ this package will contain actual PowerShell bits (i.e. it is not a meta-package). These bits are installed to `/opt/microsoft/powershell/6.0.0-alpha.8/`, where the version will change with each update -(and is the pre-release version). +(and is the prerelease version). On macOS, the prefix is `/usr/local`, instead of `/opt/microsoft` because it is derived from BSD. @@ -173,7 +168,7 @@ Start-PSPackage -Type zip -ReleaseTag v6.0.0-beta.1 -WindowsRuntime 'win7-x64' ## NuGet Packages -The NuGet packages for hosting PowerShell for Windows and non-Windows are being built in our release build pipeline. +The NuGet packages for hosting PowerShell for Windows and non-Windows are being built-in our release build pipeline. The assemblies from the individual Windows and Linux builds are consumed and packed into NuGet packages. These are then released to [powershell-core feed][ps-core-feed]. @@ -190,7 +185,7 @@ we create an [annotated tag][tag] that names the release. An annotated tag has a message (like a commit), and is *not* the same as a lightweight tag. Create one with `git tag -a v6.0.0-alpha.7 -m `, -and use the release change logs as the message. +and use the release changelogs as the message. Our convention is to prepend the `v` to the semantic version. The summary (first line) of the annotated tag message should be the full release title, e.g. 'v6.0.0-alpha.7 release of PowerShellCore'. diff --git a/global.json b/global.json index fd07d882ad3..65af5e6b4a4 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "8.0.303" + "version": "8.0.400" } } diff --git a/src/Microsoft.PowerShell.Commands.Utility/Microsoft.PowerShell.Commands.Utility.csproj b/src/Microsoft.PowerShell.Commands.Utility/Microsoft.PowerShell.Commands.Utility.csproj index e5934945216..5d0083a2fbb 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/Microsoft.PowerShell.Commands.Utility.csproj +++ b/src/Microsoft.PowerShell.Commands.Utility/Microsoft.PowerShell.Commands.Utility.csproj @@ -34,7 +34,7 @@ - + diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs index eb1b0dccc1f..7a7c112db93 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs @@ -1596,9 +1596,8 @@ internal void SetRequestContent(HttpRequestMessage request, string content) ArgumentNullException.ThrowIfNull(content); Encoding encoding = null; - string contentType = WebSession.ContentHeaders[HttpKnownHeaderNames.ContentType]; - if (contentType is not null) + if (WebSession.ContentHeaders.TryGetValue(HttpKnownHeaderNames.ContentType, out string contentType) && contentType is not null) { // If Content-Type contains the encoding format (as CharSet), use this encoding format // to encode the Body of the WebRequest sent to the server. Default Encoding format diff --git a/src/Microsoft.PowerShell.SDK/Microsoft.PowerShell.SDK.csproj b/src/Microsoft.PowerShell.SDK/Microsoft.PowerShell.SDK.csproj index be90b8849a1..7d864dcc0ff 100644 --- a/src/Microsoft.PowerShell.SDK/Microsoft.PowerShell.SDK.csproj +++ b/src/Microsoft.PowerShell.SDK/Microsoft.PowerShell.SDK.csproj @@ -17,12 +17,12 @@ - + - + - + diff --git a/test/packaging/windows/msi.tests.ps1 b/test/packaging/windows/msi.tests.ps1 index 93a56821003..14dc40a6ff2 100644 --- a/test/packaging/windows/msi.tests.ps1 +++ b/test/packaging/windows/msi.tests.ps1 @@ -115,6 +115,27 @@ Describe -Name "Windows MSI" -Fixture { $runtime = $env:PSMsiRuntime $muEnabled = Test-IsMuEnabled + if ($runtime -like '*x86*') { + $propertiesRegKeyParent = "HKLM:\SOFTWARE\Wow6432Node\Microsoft\PowerShellCore" + } else { + $propertiesRegKeyParent = "HKLM:\SOFTWARE\Microsoft\PowerShellCore" + } + + if ($channel -eq "preview") { + $propertiesRegKeyName = "PreviewInstallerProperties" + } else { + $propertiesRegKeyName = "InstallerProperties" + } + + # Rename the registry key that contains the saved installer + # properties so that the tests don't overwrite them. + $propertiesRegKeyPath = Join-Path -Path $propertiesRegKeyParent -ChildPath $propertiesRegKeyName + $propertiesBackupRegKeyName = "BackupInstallerProperties" + $propertiesBackupRegKeyPath = Join-Path -Path $propertiesRegKeyParent -ChildPath $propertiesBackupRegKeyName + if (Test-Path -Path $propertiesRegKeyPath) { + Rename-Item -Path $propertiesRegKeyPath -NewName $propertiesBackupRegKeyName + } + # Get any existing powershell in the path $beforePath = @(([System.Environment]::GetEnvironmentVariable('PATH', 'MACHINE')) -split ';' | Where-Object {$_ -like '*files\powershell*'}) @@ -133,10 +154,17 @@ Describe -Name "Windows MSI" -Fixture { AfterAll { Set-StrictMode -Version 3.0 + + # Restore the original saved installer properties registry key. + Remove-Item -Path $propertiesRegKeyPath -ErrorAction SilentlyContinue + if (Test-Path -Path $propertiesBackupRegKeyPath) { + Rename-Item -Path $propertiesBackupRegKeyPath -NewName $propertiesRegKeyName + } } BeforeEach { $error.Clear() + Remove-Item -Path $propertiesRegKeyPath -ErrorAction SilentlyContinue } Context "Upgrade code" { diff --git a/test/powershell/Host/Logging.Tests.ps1 b/test/powershell/Host/Logging.Tests.ps1 index a3c7b78745e..53798dc1c3c 100644 --- a/test/powershell/Host/Logging.Tests.ps1 +++ b/test/powershell/Host/Logging.Tests.ps1 @@ -43,6 +43,29 @@ enum LogKeyword ManagedPlugin = 0x100 } +# mac log command can emit json, so just use that +# we need to deconstruct the eventmessage to get the event id +# we also need to filter out the non-default messages +function Get-MacOsSyslogItems { + param ([int]$processId, [string]$logId) + $logArgs = "show", "--process", "$processId", "--style", "json" + log $logArgs | + ConvertFrom-Json | + Where-Object { $_.category -eq "$logId" -and $_.messageType -eq "Default" } | + ForEach-Object { + $s = $_.eventMessage.IndexOf('[') + 1 + $e = $_.EventMessage.IndexOf(']') + $l = $e - $s + if ($l -gt 0) { + $eventId = $_.eventMessage.SubString($s, $l) + } + else { + $eventId = "unknown" + } + $_ | Add-Member -MemberType NoteProperty -Name EventId -Value $eventId -PassThru + } +} + <# .SYNOPSIS Creates a powershell.config.json file with syslog settings @@ -317,26 +340,19 @@ Path:.* } } - It 'Verifies basic logging with no customizations' -Skip:(!$IsSupportedEnvironment) { + It 'Verifies basic logging with no customizations' -Skip:(!$IsMacOS) { try { + $timeString = [DateTime]::Now.ToString('yyyy-MM-dd HH:mm:ss') $configFile = WriteLogSettings -LogId $logId + copy-item $configFile /tmp/pwshtest.config.json $testPid = & $powershell -NoProfile -SettingsFile $configFile -Command '$PID' - - Export-PSOsLog -After $after -LogPid $testPid -TimeoutInMilliseconds 30000 -IntervalInMilliseconds 3000 -MinimumCount 3 | - Set-Content -Path $contentFile - $items = @(Get-PSOsLog -Path $contentFile -Id $logId -After $after -TotalCount 3 -Verbose) + $items = Get-MacOsSyslogItems -processId $testPid -logId $logId $items | Should -Not -Be $null $items.Count | Should -BeGreaterThan 2 - $items[0].EventId | Should -BeExactly 'Perftrack_ConsoleStartupStart:PowershellConsoleStartup.WinStart.Informational' - $items[1].EventId | Should -BeExactly 'NamedPipeIPC_ServerListenerStarted:NamedPipe.Open.Informational' - $items[2].EventId | Should -BeExactly 'Perftrack_ConsoleStartupStop:PowershellConsoleStartup.WinStop.Informational' - # if there are more items than expected... - if ($items.Count -gt 3) - { - # Force reporting of the first unexpected item to help diagnosis - $items[3] | Should -Be $null - } + $items.EventId | Should -Contain 'Perftrack_ConsoleStartupStart:PowershellConsoleStartup.WinStart.Informational' + $items.EventId | Should -Contain 'NamedPipeIPC_ServerListenerStarted:NamedPipe.Open.Informational' + $items.EventId | Should -Contain 'Perftrack_ConsoleStartupStop:PowershellConsoleStartup.WinStop.Informational' } catch { if (Test-Path $contentFile) { @@ -346,7 +362,7 @@ Path:.* } } - It 'Verifies scriptblock logging' -Skip:(!$IsSupportedEnvironment) { + It 'Verifies scriptblock logging' -Skip:(!$IsMacOS) { try { $script = @' $PID @@ -357,24 +373,23 @@ $PID $testScriptPath = Join-Path -Path $TestDrive -ChildPath $testFileName $script | Out-File -FilePath $testScriptPath -Force $testPid = & $powershell -NoProfile -SettingsFile $configFile -Command $testScriptPath - - Export-PSOsLog -After $after -LogPid $testPid -TimeoutInMilliseconds 30000 -IntervalInMilliseconds 3000 -MinimumCount 17 | - Set-Content -Path $contentFile - $items = @(Get-PSOsLog -Path $contentFile -Id $logId -After $after -Verbose) + $items = Get-MacOsSyslogItems -processId $testPid -logId $logId $items | Should -Not -Be $null $items.Count | Should -BeGreaterThan 2 $createdEvents = $items | Where-Object {$_.EventId -eq 'ScriptBlock_Compile_Detail:ExecuteCommand.Create.Verbose'} $createdEvents.Count | Should -BeGreaterOrEqual 3 + $createdEvents | ConvertTo-Json | set-content /tmp/createdEvents.json + # Verify we log that we are executing a file - $createdEvents[0].Message | Should -Match ($scriptBlockCreatedRegExTemplate -f ".*/$testFileName") + $createdEvents[0].EventMessage | Should -Match $testFileName # Verify we log that we are the script to create the scriptblock - $createdEvents[1].Message | Should -Match ($scriptBlockCreatedRegExTemplate -f (Get-RegEx -SimpleMatch $Script)) + $createdEvents[1].EventMessage | Should -Match (Get-RegEx -SimpleMatch $Script) # Verify we log that we are executing the created scriptblock - $createdEvents[2].Message | Should -Match ($scriptBlockCreatedRegExTemplate -f "Write\-Verbose 'testheader123' ;Write\-verbose 'after'") + $createdEvents[2].EventMessage | Should -Match "Write-Verbose 'testheader123' ;Write-verbose 'after'" } catch { if (Test-Path $contentFile) { @@ -384,35 +399,28 @@ $PID } } - It 'Verifies scriptblock logging with null character' -Skip:(!$IsSupportedEnvironment) { + It 'Verifies scriptblock logging with null character' -Skip:(!$IsMacOS) { try { $script = @' $PID & ([scriptblock]::create("Write-Verbose 'testheader123$([char]0x0000)' ;Write-verbose 'after'")) '@ $configFile = WriteLogSettings -ScriptBlockLogging -LogId $logId -LogLevel Verbose - $testFileName = 'test01.ps1' + $testFileName = 'test02.ps1' $testScriptPath = Join-Path -Path $TestDrive -ChildPath $testFileName $script | Out-File -FilePath $testScriptPath -Force - $testPid = & $powershell -NoProfile -SettingsFile $configFile -Command $testScriptPath + $testPid = & $powershell -NoProfile -SettingsFile $configFile -Command $testScriptPath | Select-Object -First 1 - Export-PSOsLog -After $after -LogPid $testPid -TimeoutInMilliseconds 30000 -IntervalInMilliseconds 3000 -MinimumCount 17 | - Set-Content -Path $contentFile - $items = @(Get-PSOsLog -Path $contentFile -Id $logId -After $after -Verbose) + $items = Get-MacOsSyslogItems -processId $testPid -logId $logId + $items | convertto-json | set-content /tmp/items.json - $items | Should -Not -Be $null - $items.Count | Should -BeGreaterThan 2 $createdEvents = $items | Where-Object {$_.EventId -eq 'ScriptBlock_Compile_Detail:ExecuteCommand.Create.Verbose'} - $createdEvents.Count | Should -BeGreaterOrEqual 3 # Verify we log that we are executing a file - $createdEvents[0].Message | Should -Match ($scriptBlockCreatedRegExTemplate -f ".*/$testFileName") - - # Verify we log that we are the script to create the scriptblock - $createdEvents[1].Message | Should -Match ($scriptBlockCreatedRegExTemplate -f (Get-RegEx -SimpleMatch $Script)) + $createdEvents[0].EventMessage | Should -Match $testFileName - # Verify we log that we are executing the created scriptblock - $createdEvents[2].Message | Should -Match ($scriptBlockCreatedRegExTemplate -f "Write\-Verbose 'testheader123␀' ;Write\-verbose 'after'") + # Verify we log the null in the message + $createdEvents[1].EventMessage | Should -Match "Write-Verbose 'testheader123\`$\(\[char\]0x0000\)' ;Write-verbose 'after'" } catch { if (Test-Path $contentFile) { @@ -422,25 +430,13 @@ $PID } } - # This is pending because it results in false postitives (-Skip:(!$IsSupportedEnvironment) ) - It 'Verifies logging level filtering works' -Pending { - try { - $configFile = WriteLogSettings -LogId $logId -LogLevel Warning - $testPid = & $powershell -NoLogo -NoProfile -SettingsFile $configFile -Command '$PID' - - Export-PSOsLog -After $after -LogPid $testPid | - Set-Content -Path $contentFile - # by default, powershell startup should only logs informational events. - # With Level = Warning, nothing should be logged. - $items = Get-PSOsLog -Path $contentFile -Id $logId -After $after -TotalCount 3 - $items | Should -Be $null - } - catch { - if (Test-Path $contentFile) { - Send-VstsLogFile -Path $contentFile - } - throw - } + # this is now specific to MacOS + It 'Verifies logging level filtering works' -skip:(!$IsMacOs) { + $configFile = WriteLogSettings -LogId $logId -LogLevel Warning + $testPid = & $powershell -NoLogo -NoProfile -SettingsFile $configFile -Command '$PID' + + $items = Get-MacOsSyslogItems -processId $testPid -logId $logId + $items | Should -Be $null -Because ("{0} Warning event logs were found" -f @($items).Count) } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 index 7fac6fad324..922483e21d0 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -692,8 +692,9 @@ Describe "Invoke-WebRequest tests" -Tags "Feature", "RequireAdminOnWindows" { $uri = Get-WebListenerUrl -Test $method $body = GetTestData -contentType $contentType $command = "Invoke-WebRequest -Uri $uri -Body '$body' -Method $method -ContentType $contentType" + $commandNoContentType = "Invoke-WebRequest -Uri $uri -Body '$body' -Method $method" - It "Invoke-WebRequest -Uri $uri -Method $method -ContentType $contentType -Body [body data]" { + It "Invoke-WebRequest -Uri $uri -Method $method -ContentType $contentType -Body [body data]" { $result = ExecuteWebCommand -command $command ValidateResponse -response $result @@ -705,6 +706,29 @@ Describe "Invoke-WebRequest tests" -Tags "Feature", "RequireAdminOnWindows" { # Validate that the response Content.data field is the same as what we sent. $jsonContent.data | Should -Be $body } + + It "Invoke-WebRequest -Uri $uri -Method $method -Body [body data]" { + + $result = ExecuteWebCommand -command $commandNoContentType + ValidateResponse -response $result + + # Validate response content + $jsonContent = $result.Output.Content | ConvertFrom-Json + $jsonContent.url | Should -Match $uri + if ($method -eq "POST") + { + $jsonContent.headers.'Content-Type' | Should -Match "application/x-www-form-urlencoded" + # Validate that the response Content.form field is the same as what we sent. + [string]$jsonContent.form | Should -Be ([string][PSCustomObject]@{$body.Split("=")[0] = [System.Object[]]}) + $jsonContent.data | Should -BeNullOrEmpty + } + else + { + # Validate that the response Content.data field is the same as what we sent. + $jsonContent.data | Should -Be $body + } + + } } } @@ -2752,6 +2776,7 @@ Describe "Invoke-RestMethod tests" -Tags "Feature", "RequireAdminOnWindows" { $uri = Get-WebListenerUrl -Test $method $body = GetTestData -contentType $contentType $command = "Invoke-RestMethod -Uri $uri -Body '$body' -Method $method -ContentType $contentType" + $commandNoContentType = "Invoke-RestMethod -Uri $uri -Body '$body' -Method $method" It "Invoke-RestMethod -Uri $uri -Method $method -ContentType $contentType -Body [body data]" { @@ -2764,6 +2789,27 @@ Describe "Invoke-RestMethod tests" -Tags "Feature", "RequireAdminOnWindows" { # Validate that the response Content.data field is the same as what we sent. $result.Output.data | Should -Be $body } + + It "Invoke-RestMethod -Uri $uri -Method $method -Body [body data]" { + + $result = ExecuteWebCommand -command $commandNoContentType + + # Validate response + $result.Output.url | Should -Match $uri + + if ($method -eq "POST") + { + $result.Output.headers.'Content-Type' | Should -Match "application/x-www-form-urlencoded" + # Validate that the response Content.form field is the same as what we sent. + [string]$result.Output.form | Should -Be ([string][PSCustomObject]@{$body.Split("=")[0] = [System.Object[]]}) + $result.Output.data | Should -BeNullOrEmpty + } + else + { + # Validate that the response Content.data field is the same as what we sent. + $result.Output.data | Should -Be $body + } + } } } diff --git a/test/tools/Modules/PSSysLog/PSSysLog.psm1 b/test/tools/Modules/PSSysLog/PSSysLog.psm1 index 7289a1b8406..4c5296d6c85 100644 --- a/test/tools/Modules/PSSysLog/PSSysLog.psm1 +++ b/test/tools/Modules/PSSysLog/PSSysLog.psm1 @@ -438,7 +438,8 @@ class PSLogItem if($item.LogId -notmatch '^\[com\.microsoft\.powershell') { - Write-Verbose "Skipping logId: $($item.LogId)" -Verbose + # this is really a lot of output, so we'll skip it for now. + # Write-Verbose "Skipping logId: $($item.LogId)" -Verbose $result = $null break } diff --git a/test/xUnit/xUnit.tests.csproj b/test/xUnit/xUnit.tests.csproj index f31a43583e9..8a084ecb6d0 100644 --- a/test/xUnit/xUnit.tests.csproj +++ b/test/xUnit/xUnit.tests.csproj @@ -25,7 +25,7 @@ - + diff --git a/tools/cgmanifest.json b/tools/cgmanifest.json index ea3bcb455b5..82262172e4e 100644 --- a/tools/cgmanifest.json +++ b/tools/cgmanifest.json @@ -125,7 +125,7 @@ "Type": "nuget", "Nuget": { "Name": "Microsoft.Extensions.ObjectPool", - "Version": "8.0.7" + "Version": "8.0.8" } }, "DevelopmentDependency": false @@ -195,7 +195,7 @@ "Type": "nuget", "Nuget": { "Name": "Microsoft.Windows.Compatibility", - "Version": "8.0.7" + "Version": "8.0.8" } }, "DevelopmentDependency": false @@ -475,7 +475,7 @@ "Type": "nuget", "Nuget": { "Name": "System.Drawing.Common", - "Version": "8.0.7" + "Version": "8.0.8" } }, "DevelopmentDependency": false @@ -525,7 +525,7 @@ "Type": "nuget", "Nuget": { "Name": "System.Net.Http.WinHttpHandler", - "Version": "8.0.1" + "Version": "8.0.2" } }, "DevelopmentDependency": false diff --git a/tools/ci.psm1 b/tools/ci.psm1 index 751b5fd4146..37d9a06ac60 100644 --- a/tools/ci.psm1 +++ b/tools/ci.psm1 @@ -537,7 +537,7 @@ function Invoke-CIFinish switch -regex ($Runtime){ default { $runPackageTest = $true - $packageTypes = 'msi', 'nupkg', 'zip', 'zip-pdb', 'msix' + $packageTypes = 'msi', 'zip', 'zip-pdb', 'msix' } 'win-arm.*' { $runPackageTest = $false @@ -591,14 +591,6 @@ function Invoke-CIFinish throw "Packaging tests failed ($($packagingTestResult.FailedCount) failed/$($packagingTestResult.PassedCount) passed)" } } - - # only publish assembly nuget packages if it is a daily build and tests passed - if (Test-DailyBuild) { - $nugetArtifacts = Get-ChildItem $PSScriptRoot\packaging\nugetOutput -ErrorAction SilentlyContinue -Filter *.nupkg | Select-Object -ExpandProperty FullName - if ($nugetArtifacts) { - $artifacts.AddRange(@($nugetArtifacts)) - } - } } } catch { Get-Error -InputObject $_ diff --git a/tools/packaging/packaging.psm1 b/tools/packaging/packaging.psm1 index 209d8fc49f7..07c43c21802 100644 --- a/tools/packaging/packaging.psm1 +++ b/tools/packaging/packaging.psm1 @@ -50,7 +50,7 @@ function Start-PSPackage { [string]$Name = "powershell", # Ubuntu, CentOS, Fedora, macOS, and Windows packages are supported - [ValidateSet("msix", "deb", "osxpkg", "rpm", "rpm-fxdependent", "rpm-fxdependent-arm64", "msi", "zip", "zip-pdb", "nupkg", "tar", "tar-arm", "tar-arm64", "tar-alpine", "fxdependent", "fxdependent-win-desktop", "min-size", "tar-alpine-fxdependent")] + [ValidateSet("msix", "deb", "osxpkg", "rpm", "rpm-fxdependent", "rpm-fxdependent-arm64", "msi", "zip", "zip-pdb", "tar", "tar-arm", "tar-arm64", "tar-alpine", "fxdependent", "fxdependent-win-desktop", "min-size", "tar-alpine-fxdependent")] [string[]]$Type, # Generate windows downlevel package @@ -321,18 +321,18 @@ function Start-PSPackage { if (-not $Type) { $Type = if ($Environment.IsLinux) { if ($Environment.LinuxInfo.ID -match "ubuntu") { - "deb", "nupkg", "tar" + "deb", "tar" } elseif ($Environment.IsRedHatFamily) { - "rpm", "nupkg" + "rpm" } elseif ($Environment.IsSUSEFamily) { - "rpm", "nupkg" + "rpm" } else { throw "Building packages for $($Environment.LinuxInfo.PRETTY_NAME) is unsupported!" } } elseif ($Environment.IsMacOS) { - "osxpkg", "nupkg", "tar" + "osxpkg", "tar" } elseif ($Environment.IsWindows) { - "msi", "nupkg", "msix" + "msi", "msix" } Write-Warning "-Type was not specified, continuing with $Type!" } @@ -521,20 +521,6 @@ function Start-PSPackage { New-MSIXPackage @Arguments } } - 'nupkg' { - $Arguments = @{ - PackageNameSuffix = $NameSuffix - PackageSourcePath = $Source - PackageVersion = $Version - PackageRuntime = $Runtime - PackageConfiguration = $Configuration - Force = $Force - } - - if ($PSCmdlet.ShouldProcess("Create NuPkg Package")) { - New-NugetContentPackage @Arguments - } - } "tar" { $Arguments = @{ PackageSourcePath = $Source @@ -3051,95 +3037,6 @@ function Publish-NugetToMyGet } } -<# -.SYNOPSIS -The function creates a nuget package for daily feed. - -.DESCRIPTION -The nuget package created is a content package and has all the binaries laid out in a flat structure. -This package is used by install-powershell.ps1 -#> -function New-NugetContentPackage -{ - [CmdletBinding(SupportsShouldProcess=$true)] - param ( - - # Name of the Product - [ValidateNotNullOrEmpty()] - [string] $PackageName = 'powershell', - - # Suffix of the Name - [string] $PackageNameSuffix, - - # Version of the Product - [Parameter(Mandatory = $true)] - [ValidateNotNullOrEmpty()] - [string] $PackageVersion, - - # Runtime of the Product - [Parameter(Mandatory = $true)] - [ValidateNotNullOrEmpty()] - [string] $PackageRuntime, - - # Configuration of the Product - [Parameter(Mandatory = $true)] - [ValidateNotNullOrEmpty()] - [string] $PackageConfiguration, - - # Source Path to the Product Files - required to package the contents into an Zip - [Parameter(Mandatory = $true)] - [ValidateNotNullOrEmpty()] - [string] $PackageSourcePath, - - [Switch] - $Force - ) - - Write-Log "PackageVersion: $PackageVersion" - $nugetSemanticVersion = Get-NugetSemanticVersion -Version $PackageVersion - Write-Log "nugetSemanticVersion: $nugetSemanticVersion" - - $nugetFolder = New-SubFolder -Path $PSScriptRoot -ChildPath 'nugetOutput' -Clean - - $nuspecPackageName = $PackageName - if ($PackageNameSuffix) - { - $nuspecPackageName += '-' + $PackageNameSuffix - } - - # Setup staging directory so we don't change the original source directory - $stagingRoot = New-SubFolder -Path $PSScriptRoot -ChildPath 'nugetStaging' -Clean - $contentFolder = Join-Path -Path $stagingRoot -ChildPath 'content' - if ($PSCmdlet.ShouldProcess("Create staging folder")) { - New-StagingFolder -StagingPath $contentFolder -PackageSourcePath $PackageSourcePath - } - - $projectFolder = Join-Path $PSScriptRoot 'projects/nuget' - - $arguments = @('pack') - $arguments += @('--output',$nugetFolder) - $arguments += @('--configuration',$PackageConfiguration) - $arguments += "/p:StagingPath=$stagingRoot" - $arguments += "/p:RID=$PackageRuntime" - $arguments += "/p:SemVer=$nugetSemanticVersion" - $arguments += "/p:PackageName=$nuspecPackageName" - $arguments += $projectFolder - - Write-Log "Running dotnet $arguments" - Write-Log "Use -verbose to see output..." - Start-NativeExecution -sb {dotnet $arguments} | ForEach-Object {Write-Verbose $_} - - $nupkgFile = "${nugetFolder}\${nuspecPackageName}-${packageRuntime}.${nugetSemanticVersion}.nupkg" - if (Test-Path $nupkgFile) - { - Get-Item $nupkgFile - } - else - { - throw "Failed to create $nupkgFile" - } -} - function New-SubFolder { [CmdletBinding(SupportsShouldProcess=$true)] diff --git a/tools/packaging/projects/nuget/package.csproj b/tools/packaging/projects/nuget/package.csproj deleted file mode 100644 index 390283c5ef1..00000000000 --- a/tools/packaging/projects/nuget/package.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - - NotUsed - PowerShell nuget package with .NET CLI host including everything needed to run it. - powershell.nuspec - runtime=$(RID);version=$(SemVer);PackageName=$(PackageName) - $(StagingPath) - True - net8.0 - - diff --git a/tools/packaging/projects/nuget/powershell.nuspec b/tools/packaging/projects/nuget/powershell.nuspec deleted file mode 100644 index 5c191e911e5..00000000000 --- a/tools/packaging/projects/nuget/powershell.nuspec +++ /dev/null @@ -1,21 +0,0 @@ - - - - $PackageName$-$runtime$ - $version$ - PowerShell for $runtime$ - PowerShell - PowerShell - false - MIT - https://github.com/powershell/powershell - https://github.com/PowerShell/PowerShell/blob/master/assets/Powershell_64.png - This package contains PowerShell for $runtime$. - Copyright (c) Microsoft Corporation. - PowerShell - - - - - - diff --git a/tools/performance/README.md b/tools/performance/README.md index c598fca5f28..e0c79659de2 100644 --- a/tools/performance/README.md +++ b/tools/performance/README.md @@ -3,7 +3,7 @@ This directory contains useful scripts and related files for analyzing PowerShell performance. -If you use the [Windows Performance Toolkit](https://developer.microsoft.com/en-US/windows/downloads/windows-10-sdk), you can use the following to collect data and analyze a trace. +If you use the [Windows Performance Toolkit](https://learn.microsoft.com/windows-hardware/test/wpt/), you can use the following to collect data and analyze a trace. ```PowerShell $PowerShellGitRepo = "D:\PowerShell"